将stdout重定向到管道时,python子进程输出消失

时间:2014-05-20 21:40:06

标签: python subprocess output

我目前正在处理一段代码,该代码使用一个脚本来获取实时数据并将其打印到我的屏幕上。

当我在python控制台中运行脚本(我无法访问视图)时,使用:

>>>> myproc = subprocess.Popen('command')
...print....

当数据到来时,输出完美地打印在我的屏幕上。

但是,如果我将其更改为

>>>> myproc = subprocess.Popen('command', stdout = subprocess.PIPE, stderr = subprocess.PIPE)`
>>>> while True:
>>>>    print(myproc.stdout.readline())
... perfectly no print....

输出为零(我还检查了stderr,没有)

我想这里的问题是我将stdout设置为subprocess.PIPE,我应该改变它。

但是,由于我需要存储来自myproc的数据,并且使用stdout到目前为止我知道的唯一方法可以让我这样做,我已经用完了关于如何更改我的代码的想法。

请告诉我在这里可以做些什么,还请告诉我为什么会这样。

由于

编辑:我的脚本侦听实时数据,因此它会一直运行,直到我手动中断它为止。我想在它实际终止之前打印。

第二次编辑

我发现丢失的输出去了......我必须把它改成

myproc = subprocess.Popen('command', stdout=sys.stdout)然后使用

While True:
    if myproc.stdout is not None:
          print(myproc.stdout)

显示输出。但这只是超级丑陋而且输出可能非常难以预测。任何人都可以提供更好的方法来处理这个丑陋的事情吗?

2 个答案:

答案 0 :(得分:1)

您应该使用通信来等待进程完成并获取stdout和stderr处理程序:

myproc = subprocess.Popen(['command'], stdout = subprocess.PIPE, stderr = subprocess.PIPE)
out, err = myproc.communicate()
print("STDOUT:")
for line in myproc.stdout:
    print(line)
print("STDERR:")
for line in myproc.stderr:
    print(line)

另一种可能性是它打印到stderr而不是stdout。

最后,如果使用命令的单个字符串参数调用Popen,则还应设置shell=True以生成shell,否则应使用列表。虽然如果你没有任何参数,它可以在不使用列表的情况下工作。


然后您可能会对以下代码段感兴趣:

    p = subprocess.Popen([command], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    out = io.TextIOWrapper(p.stdout)
    err = io.TextIOWrapper(p.stderr)
    while p.poll() == None:
        ret = select.select([out.fileno(), err.fileno()], [], [])
        for fd in ret[0]:
            if fd == out.fileno():
                output_parser(out.readline())
            if fd == err.fileno():
                output_parser(err.readline())
    for line in out.read().split('\n'):
        output_parser(line)
    for line in err.read().split('\n'):
        output_parser(line)

取自我最近写的代码:

https://github.com/guyzmo/pyvod/blob/master/vod/video.py#L70

HTH

答案 1 :(得分:1)

如果这是linux或osx,问题是您需要使用伪终端使程序认为它应该以交互方式运行。构建python pexpect模块来处理这个问题。它创建了一个pty并将其用于stdout。您可以直接使用pexpect或阅读其来源,了解烹饪自己的东西。此示例将命令输出发送到屏幕和磁盘上的文件。

import pexpect
proc = pexpect.spawn('command', logfile=open('mylog.txt','w'),
    searchwindowsize=80, timeout=-1)
for line in proc:
    print(line.strip())