在后台执行外部 Python 文件并在 python 中获取输出

Executing external Python file in background and get output in python

我有一个 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

问题是第二个脚本的输出一直在打印'Main Thread...'我无法读取任何输出。

谢谢。

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

简短的回答是将 运行 替换为:

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 时,打印正在写入终端,因此它是无缓冲的,您的提示会立即出现。但是当你 运行 odev2.py 与 subprocess(stdout=PIPE) 时,odev2.py 正在获取一个管道作为标准输出,以便文件对象缓冲。这意味着您没有看到提示。

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

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

Note: -u turns off all buffering, which can have a huge impact on performance. So this is only a quick and dirty solution

其次,您的阅读线程使用readline。 readline 在看到换行符之前不会 return,但是 odev2.py 的提示不会以换行符结尾。所以 运行 中的 readline 不会 return 直到 odev2.py 发送一个换行符,但是 odev2 不会发送一个换行符直到它从你那里读取一些输入。所以你陷入了僵局。

解决这个问题的可靠解决方案是用 non-blocking IO 替换 readline,这样 return 你可以得到什么。但是 there doesn't seem 是在 python 2.7 中做到这一点的一种便携方式。所以快速黑客是做单字符读取。所以不用做 popen.stdout.readline(),你只要做 popen.stdout.read(1).