我正在使用 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
这适用于许多基本用例,如 ls -al
或类似的。但是,我想知道如何处理从较长(或无限期)运行的进程(例如 tail -f foo.log
)中定期且一致地获取输出。有没有办法在循环中定期读取标准输出?或者产生一个线程来定期检查并返回每个线程?这里最好的方法是什么?
谢谢!
最佳答案
我认为重要的是要注意原始代码不正确(或者说不安全)。 它通常会工作,但在您给定的示例中没有任何内容等待进程退出。它可能仍在运行。
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()
我愿意就您应该如何实际访问文件对象 stdout
和 stderr
发表评论,但这是我临时想到的。
尽管这是处理派生子进程的最可靠方法,但如果可以的话,请认真考虑使用 process.wait()
—— 它只会让一切变得更简单。
关于python - 如何使用子进程和 Popen 从长时间运行的进程返回标准输出?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22263283/