1

我已经阅读并尝试了 8 种不同的方法来回答有关此问题的几个问题。我在 python 中打开了一个进程并想读取它的输出,即使该进程尚未终止。该过程通常不会完成至少 1 分钟或直到发送中断。无论我尝试什么,我都无法让它读取输出。我知道我传递的命令和参数工作,因为当我将其更改为 subprocess.call(cmd, args) 时,它会将所有内容打印到屏幕上。我还检查了该进程是否正在使用 ps -ax 运行。这是我正在尝试的示例(cat /dev/random 与我的项目无关):

proc = subprocess.Popen(["cat", "/dev/random"], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
print("Process started.")

这是我迄今为止尝试过的失败的方法:

for line in iter(p.stdout.readline, ''):
    strLine = str(line).rstrip()
    print(">>> " + strLine )
    sys.stdout.flush()

output, error = proc.communicate()
print output

while proc.poll() is None:
    print("Still waiting.")
    print(proc.stdout.readline(1))

我尝试了更多解决方案,这些解决方案是这种情况的变体,但没有运气。在不更改标准输出的情况下使用调用函数时,所有内容都会正确打印到控制台。我究竟做错了什么?

我正在使用 Python 2.6。

4

1 回答 1

2

我将您的代码复制到一个完整的函数和文件中,添加了一个更改 ( repr) 以避免打印更改终端标题等的内容,给出:

import subprocess
import sys

def tst():
    proc = subprocess.Popen(["cat", "/dev/random"],
        stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    print("Process started.")
    for line in iter(p.stdout.readline, ''):
        strLine = str(line).rstrip()
        print(">>> " + repr(strLine))
        sys.stdout.flush

tst()

(哎呀,看起来我的剪切和粘贴删除了 sys.stdout.flush 上的括号!不过在这种情况下是无害的)

立即运行它会产生明显的错误:

Process started.
Traceback (most recent call last):
  File "foo.py", line 13, in <module>
    tst()
  File "foo.py", line 8, in tst
    for line in iter(p.stdout.readline, ''):
NameError: global name 'p' is not defined

修复该问题(替换pproc),该示例有效,对于“有效”的某些定义: /dev/random 不会停止产生输出,因此它会永远运行。

中间的例子将是一个问题,因为proc.communicate()要读取进程的整个输出,这是无限的,因此会耗尽你的内存(最终)。:-)

第三个示例运行良好。

如果您将 替换为cat /dev/random其他内容,您可能会发现 Unix/Linux 管道的一个更有趣且可能令人讨厌的方面:进程的标准输出流通常是行缓冲的,当且仅当它进入“交互式设备”(如终端窗口) . 管道不是“交互式设备”,因此 stdout 是块缓冲的,除非相关命令本身覆盖它。这可能是我无法在这里重现的问题的根源。

您可以通过使用伪 ttys 代替(或附加于)Pythonsubprocess模块来解决此问题。

于 2013-05-29T05:58:59.300 回答