【问题标题】:How to return stdout from long running process with subprocess and Popen?如何使用子进程和 Popen 从长时间运行的进程中返回标准输出?
【发布时间】:2014-04-11 09:05:51
【问题描述】:

我正在使用带有 subprocess.Popen() 的非常基本的设置并将标准输出定向到一个变量,我稍后将返回到我的 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)定期和一致地获取输出。有没有办法在循环中定期读取标准输出?或者生成一个线程来定期检查并返回每个线程?这里最好的方法是什么?

谢谢!

【问题讨论】:

标签: python shell subprocess stdout


【解决方案1】:

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

process.poll()process.wait() 是实现此目的的两个不错的选择。


当您不知道输出可能有多大时,communicate 很危险,因为它会将输出缓冲到内存中,并且可能会耗尽您的内存。但是,如果您使用的是subprocess.PIPE,则可能无论如何都会发生这种情况。

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


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

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()

对于您应该如何实际访问文件对象 stdoutstderr,我对 cme​​ts 持开放态度,但这是临时想到的。

虽然这是处理生成的子进程的最可靠的方法,但如果可以的话,请认真考虑使用 process.wait() —— 它只会让一切变得更简单。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-04-06
    • 1970-01-01
    • 1970-01-01
    • 2010-12-10
    • 2016-08-20
    • 2011-08-31
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多