如何使用子进程和Popen从长时间运行的进程返回stdout?

cal*_*umb 5 python shell subprocess stdout

我正在使用subprocess.Popen()的一个非常基本的设置,并将stdout指向一个变量,我稍后将其返回到我的python脚本的不同部分.

这是我的基本Popen代码:

process = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
# wait for the process to terminate
out, err = process.communicate()
errcode = process.returncode
print out
Run Code Online (Sandbox Code Playgroud)

这适用于许多类似ls -al或类似的基本用例.但是,我想知道如何处理从更长(或无限期)运行过程中定期和一致地获取输出,例如tail -f foo.log.有没有办法在循环中定期读取stdout?或者产生一个线程来检查并定期返回每个线程?这里最好的方法是什么?

谢谢!

sir*_*sen 5

我认为重要的是要注意原始代码不正确(或者说,不安全).它通常会起作用,但是在给定的示例中没有任何内容等待进程退出.它可能仍在运行.

process.poll()并且process.wait()是用于此目的的两个好选择.


当你不知道输出有多大时,会communicate很危险,因为它会将输出缓冲到内存中,并且可能会让你失去内存.但是,如果你正在使用,那么subprocess.PIPE无论如何都可能发生这种情况.

你应该仔细选择目标stdout,并stderr根据您的需要.如果它可能非常大,写入磁盘上的文件可能是最好的选择.然而,这是一个单独的讨论.


要在不等待进程关闭的情况下查看输出,您应该在单独的线程中运行类似的东西:

while process.returncode is None:
    # handle output by direct access to stdout and stderr
    for line in process.stdout:
        print line
    # set returncode if the process has exited
    process.poll()
Run Code Online (Sandbox Code Playgroud)

我接受你应该如何实际访问文件对象的意见stdoutstderr,但是这是浮现在脑海的副手.

虽然这是处理衍生子进程的最强大方法,但process.wait()如果可以的话,请仔细考虑使用- 它只会使一切变得更加简单.