Python 子进程在流式输出时在命令行和 GUI 控制台中表现出不同的行为

Python subprocess exhibits different behavior in command line and GUI console while streaming ouput

我正在使用 python27 库的子进程从另一个 python 文件(sample.py 运行 一个大的 python 文件(execute.py) ]).

如果我在 windows 命令行中 运行 sample.py(它有子进程语句),它会 运行 正确地传输实时输出。

但是在 python GUI 控制台中,当我 运行 GUI python 文件(具有相同的子进程语句)时,GUI window 有几分钟没有响应一段时间后,输出作为整体打印(不是流式传输)。

这是片段:

cmdlist = ["python", "execute.py","name","xyz"]
proc = subprocess.Popen(cmdlist, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)

for line in iter(proc.stdout.readline, ""):
        self.output.write(line)

self.output.write("\n Finished process\n")

折腾了一个星期,一直没找到解决方法

当您在命令行中 运行 脚本时:输出将直接发送到终端。 Python GUI 控制台(IDLE)基于 tkinter 工具包,因此当您 运行 脚本时: 输出将发送到缓冲区。 GUI 工具需要一些时间才能将缓冲区显示到屏幕上。因此 运行 命令行显示输出的时间会更长。如果您的脚本打印太多,缓冲区将溢出然后 "Not responding" 发生。

如果您希望它们转到外部(控制)进程,请不要设置 stdoutstderr

cmdlist = ["python", "execute.py","name","xyz"]
proc = subprocess.Popen(cmdlist)
# do other stuff here if you like
self.output.write(
  "\n Finished process (%s)\n" % proc.wait()  # wait until process has finished; process will stream to stdout/stderr while we wait
)

如果您将 stdoutstderr 设置为 subprocess.PIPE,您当前的 (python) 进程会创建一个 new 管道它与子进程通信。基本上,您自己的进程将缓冲子进程的输出。

即使您没有显式缓冲任何内容,python 本身也会进行一些缓冲。这尤其适用于当您重定向 stderr 并将其写入您自己的 stdout 时 - 默认情况下会缓冲 stdout,而 stderr 则不会。许多程序还写入 同一行 并重置光标,因此 proc.stdout.readline() 将缓冲,等待该行完成。

现在,如果您不设置 stdoutstderr,子进程将 继承 您的 stdoutstderr.这意味着它可以直接写入外部控制进程。