【问题标题】:python stream subprocess stdout and stderr zip doesnt workpython流子进程stdout和stderr zip不起作用
【发布时间】:2016-01-13 21:45:26
【问题描述】:

已经有很多答案可以解决如何做这个一般的事情,但我的主要问题是为什么这种方法不起作用?

我正在尝试从子进程“直播”标准输出和标准错误。我可以这样做:

import sys
import subprocess

def run_command(cmd):
    process = subprocess.Popen(cmd, stderr=subprocess.PIPE, stdout=subprocess.PIPE)

    for out in iter(process.stdout.readline, b''):
        print(out)

    for err in iter(process.stderr.readline, b''):
        print(err)

run_command(['echo', 'hello', 'world']) # should print hello world
run_command(['rm', 'blarg223'])  # Should print to stderr (file doesnt exist)

这给了我结果:

b'hello world\n'
b'rm: cannot remove \xe2\x80\x98blarg223\xe2\x80\x99: No such file or directory\n'

但是这会导致一个问题,因为它实际上只实时流式传输标准输出,然后将所有错误打印为结尾。所以我想我可以使用以下方法解决这个问题:

def run_command(cmd):
    process = subprocess.Popen(cmd, stderr=subprocess.PIPE, stdout=subprocess.PIPE)

    for out, err in zip(iter(process.stdout.readline, b''), iter(process.stderr.readline, b'')):
        print(out)
        print(b'Error: ' + err)

但是,这不会产生任何输出。为什么使用 zip 不起作用?

【问题讨论】:

  • 您是否希望在 stdout 和 stderr 行之间始终保持一一对应关系?您正在尝试成对排列。
  • 如果 stdout/stderr 不产生相同数量的输出(大于阈值),这两个代码示例都可能导致死锁
  • @J.F.Sebastian 怎么样?我已经对其进行了测试,它似乎可以工作。你能举例说明死锁是如何发生的吗?
  • @NickHumrich:如果您无法创建导致死锁的示例,请提出单独的问题。

标签: python python-3.x subprocess


【解决方案1】:

当其中一个迭代器完成时,zip 停止。

在您给出的每个示例中,一个流(stdout/stderr)是空的。所以 zip 不会产生任何结果。

要解决这个问题,您应该使用 itertools.zip_longest

【讨论】:

  • @NickHumrich: zip_longest() 在一般情况下不会修复死锁。问题中的代码已损坏。如果您想将 stdout/stderr 单独读取为“实时流”;您应该同时阅读管道,例如use threads,或使用a select()-loop
猜你喜欢
  • 1970-01-01
  • 2011-07-07
  • 2023-04-06
  • 2018-03-16
  • 1970-01-01
  • 2020-06-23
  • 1970-01-01
  • 2020-05-31
  • 2016-09-04
相关资源
最近更新 更多