【问题标题】:Python subprocess stdout iterator always blocksPython子进程标准输出迭代器总是阻塞
【发布时间】:2017-07-06 16:45:09
【问题描述】:

我想在打印时捕获输出,但我会永远阻塞,甚至连一行都不读。 发生了什么?我正在使用 Python2。

生成器脚本:

#!/usr/bin/env python2.7

import random
import time

while True:
    print(random.random())
    time.sleep(1)

样本生成器输出:

$ ./generator.py 
0.334835137212
0.896609571236
0.833267988558
0.55456332113
^CTraceback (most recent call last):

阅读器脚本:

import subprocess

cmd = ['./generator.py']
p = subprocess.Popen(cmd, stdout=subprocess.PIPE)

for line in p.stdout:
    print(line)
    print('Looping')

p.wait()

我也试过了:

import subprocess
import sys

cmd = ['./generator.py']
p = subprocess.Popen(cmd, stdout=subprocess.PIPE)

while True:
    line = p.stdout.readline()
    print(line)

    print('Looping')

p.wait()

...和:

import sys
import subprocess
import select
import time

cmd = ['./generator.py']
p = subprocess.Popen(cmd, stdout=subprocess.PIPE)

s = select.poll()
s.register(p.stdout, select.POLLIN)

while True:
    if s.poll(1):
        line = p.stdout.read()
    else:
        p.poll()
        if p.returncode is not None:
            break

    print('Looping')
    time.sleep(1)

p.wait()

【问题讨论】:

  • 你应该使用p.communicate(),而不是直接使用stdout。见docs.python.org/2/library/… ...
  • 你是如何执行这些脚本的?从stdout 读取不是通常的进程间通信尝试。
  • @CorleyBrigman 使用communicate() 对长时间运行的进程毫无用处。直到最后你才能打印出来。
  • @Prune IPC 不是必需的。我需要做的就是在捕获输出时迭代地打印输出。
  • 这在生成器中缺少sys.stdout.flush()(或flush=True)。否则,您将不得不等到它填满输出缓冲区,这 -- 鉴于 sleep(1) -- 可能需要一段时间。

标签: python


【解决方案1】:

正如@dhke 提到的,问题之一是生产者中的隐式输出缓冲。如果您有能力更改生产者,并且您愿意,并且生产是通过调用打印函数完成的,那么只需将“flush = True”作为参数添加到@ 987654321@ 功能。您也可以回退到在生产者的关键点执行sys.stdout.flush()

第二个问题似乎是迭代sys.stdout。这似乎永远不适用于长期运行的过程。第二种和第三种方法

【讨论】:

    【解决方案2】:

    我正在处理类似的问题。这是我目前用来防止缓冲的解决方法。

    proc = subprocess.Popen(['stdbuf', '-o0'] + cmd, stdout=subprocess.PIPE)
    

    这种方法的缺点是它依赖于外部 Linux 命令来解决问题。查看 cmets here 以了解一种不同的原生 python 方法来摆脱 PIPE 缓冲。非常感谢 @9000 向我提出这两种解决方案。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-12-07
      • 2016-07-28
      • 2014-03-29
      • 2010-11-19
      • 2012-01-18
      • 2011-10-17
      • 1970-01-01
      相关资源
      最近更新 更多