【问题标题】:python subprocess output disappear when redirect stdout to pipe将stdout重定向到管道时python子进程输出消失
【发布时间】:2014-05-20 21:40:05
【问题描述】:

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

当我在 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)

用于显示输出。但这只是超级丑陋,输出可能非常不可预测。任何人都可以提供更好的方法来解决这个丑陋的事情吗??

【问题讨论】:

  • 这是linux还是windows?
  • 循环中的myproc.poll() 是什么(进程可能无法静默启动)?不要使用stderr=PIPE,除非您(同时)阅读它。你想把输出数据保存在哪里(你的代码只是打印到标准输出),你想过滤数据,例如sys.stdout.write(your_python_filter(myproc.stdout.readline())),还是只保存到一个文件或两者兼而有之? command |& cat 是否在 bash 中工作(你看到任何输出)吗?是缓冲问题吗?见Python subprocess readlines() hangs
  • @J.F.Sebastian .poll() 将挂起,因为程序不会自行终止
  • poll() 立即返回。它不是等待()。如果进程仍在运行,则返回 None。如果它返回任何其他内容,则应该中断循环——这意味着子进程过早结束。

标签: python subprocess output


【解决方案1】:

如果这是linux或osx,问题是你需要使用伪终端让程序认为它应该交互操作。 python pexpect 模块就是为了处理这个问题而构建的。它创建一个 pty 并将其用于标准输出。您可以直接使用 pexpect 或阅读其源代码以了解如何制作自己的东西。此示例将命令输出发送到屏幕和磁盘上的文件。

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

【讨论】:

【解决方案2】:

您应该使用通信来等待进程完成并获取 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,否则你应该使用一个列表。虽然如果你没有任何参数,它可以在不使用列表的情况下工作。


那你可能对以下sn-p感兴趣:

    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

【讨论】:

  • 这在我的情况下不起作用,因为脚本会监听实时数据并且永远不会终止,除非我手动中断它(或杀死它)
猜你喜欢
  • 2012-02-11
  • 2019-02-08
  • 1970-01-01
  • 1970-01-01
  • 2012-07-14
  • 2018-04-13
  • 1970-01-01
  • 2013-07-16
  • 1970-01-01
相关资源
最近更新 更多