【问题标题】:Executing external Python file in background and get output in python在后台执行外部 Python 文件并在 python 中获取输出
【发布时间】:2018-02-15 13:06:07
【问题描述】:

我有一个 python 文件,它接受一些输入并根据这些输入打印输出。我试图在另一个脚本中执行这个脚本。我需要做的就是向这个文件发送一些参数并在这个脚本中获取输出。

我需要执行的脚本:

while True:
  print("Sabah 1")
  print("Oglen 2")
  print("Aksam 3")
  print("Gece 4")
  print("---------")


  secim = raw_input("Gun icerisindeki zaman dilimini giriniz")

  isim = raw_input("Isminizi giriniz.")


  if (secim=='1') : 
      print("Gunaydin"+isim)
  elif (secim == '2'):
      print("Tunaydin"+isim)
  elif (secim == '3'):
      print("iyi aksamlar"+isim)
  elif (secim == '4'):
      print("Iyi geceler"+isim)
  else:
      print("Program sonlandiriliyor")
      break

应该执行上述脚本的脚本:

import subprocess, threading, time
can_break = False

def run():
    args = ['python','odev2.py','arg1','arg2']
    popen = subprocess.Popen(args,shell=False,stdout=subprocess.PIPE)
    while not can_break:
        print(popen.stdout.readline())


t = threading.Thread(target=run)

try:
    t.start()
    while True: 
        print('Main Thread.... ')
        time.sleep(1)
except KeyboardInterrupt:
    can_break_break = True

问题是第二个脚本的输出不断打印“主线程...”我无法读取任何输出。

谢谢。

【问题讨论】:

    标签: python subprocess stdout execute


    【解决方案1】:

    我假设您想知道为什么您没有看到来自 odev2.py 的任何提示?

    简短的回答是将 run 替换为:

    def run():
        args = ['python','-u','odev2.py','arg1','arg2']
        popen = subprocess.Popen(args,shell=False,stdout=subprocess.PIPE)
        while not can_break:
            sys.stdout.write(popen.stdout.read(1))
    

    长答案是有两个问题。

    首先,有缓冲。 IO 是昂贵的,所以不是立即写出数据,File 对象有时会收集缓冲区中的数据,并且仅在缓冲区已满时才将数据写出。内置文件对象(如 sys.stdout)将根据它们写入的内容决定缓冲。如果他们正在写入终端,那么他们将关闭缓冲,以便立即将输出发送给用户。但如果他们正在写入文件,他们会缓冲以提高效率。

    因此,当您在命令行运行 odev2.py 时,print 正在写入终端,因此它是无缓冲的,并且您的提示会立即出现。但是,当您使用 subprocess(stdout=PIPE) 运行 odev2.py 时,odev2.py 会获取管道作为标准输出,因此文件对象会缓冲。这意味着您看不到提示。

    您可以使用 'python odev2.py arg1 arg2 | 从命令行运行 odev2.py 看到相同的效果。猫'。这会将标准输出设置为管道,您不会看到任何提示,但 odev2.py 将等待您输入。

    这个缓冲问题可以通过让 odev2.py 自己编写提示(而不是让 raw_input 打印它们)然后在适当的时间调用 sys.stdout.flush() 来解决。但是一种快速而肮脏的方法是使用关闭所有缓冲的 -u 标志运行 python。尝试'python -u odev2.py arg1 arg2 | cat' 看看有什么不同。

    注意:-u 关闭所有缓冲,这会对性能产生巨大影响。所以这只是一个快速而肮脏的解决方案

    其次,您的阅读线程使用 readline。 readline 在看到换行符之前不会返回,但 odev2.py 的提示不会以换行符结尾。因此,在 odev2.py 发送换行符之前,运行中的 readline 不会返回,但 odev2 在读取您的一些输入之前不会发送换行符。所以你陷入了僵局。

    对此的可靠解决方案是将 readline 替换为非阻塞 IO,它将返回可用的内容。但是there doesn't seem 在 python 2.7 中是一种可移植的方式。所以快速破解是进行单字符读取。所以不要执行popen.stdout.readline(),你只需执行popen.stdout.read(1)。

    【讨论】:

    • 非常感谢你的朋友。
    猜你喜欢
    • 2016-01-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-13
    相关资源
    最近更新 更多