从子进程获取未缓冲的输出不起作用Python

问题描述 投票:0回答:2

我有一个可执行文件,如果我使用标志运行它,它会启动一个始终生成消息的工具。 当我尝试使用子进程运行它时,我将输出发送到cmd,这很好。 问题是我想获取这些消息并对其执行某些操作,但由于某种原因,取消缓冲方法不起作用,并且我没有收到任何消息。

以下是我尝试过的代码:

p = subprocess.Popen(
 ["my_tool.exe","runMode","y","port","1234"],stdout=subprocess.PIPE,stderr=subprocess.STDOUT, bufsize=1)

要生成输出,请尝试以下操作:

for line in p.stdout:
    print("CUR", line)

和:

while p.poll() is None:
    line = p.stdout.read(2)
    print("Print:" + line)

和:

for line in iter(p.stdout.readline, b''):
    print(line)
p.stdout.close()

知道为什么代码总是阻塞在标准输出行上吗?

更新:

例如,如果我有以下无限程序:

inf.py

import time
i = 0
while True:
    time.sleep(0.5)
    print(i)
    i += 1

以及运行它的以下代码:

p = subprocess.Popen(r"C:\Python35\python.exe inf.py",
                     stdout=subprocess.PIPE, bufsize=1, universal_newlines=True)

为了生成输出,我正在使用上述方法之一,如果我使用 CTRL+ C 停止它,它总是卡在这一行:

  File "C:\Python35\lib\encodings\cp1252.py", line 22, in decode
    def decode(self, input, final=False):
python subprocess stdout unbuffered
2个回答
0
投票

首先我设置以下环境变量:

PYTHONUNBUFFERED=1

然后我稍微改变了你的代码:

read_infinite.py

import subprocess

binary = "C:\\Python35\\python.exe"
script = "C:\\temp\\python\\tests\\inf.py"

p = subprocess.Popen([binary, script], stdout=subprocess.PIPE, bufsize=1, universal_newlines=True)

while p.poll() is None:
    #line = p.stdout.read(2)
    line = p.stdout.readline()
    if line:
        print("Result: %r" % line)

删除

bufsize=1
效果相同。

我一开始遇到的错误是找不到 inf.py,但这并没有显示出来,因为 read_infinite.py 的打印将错误滚动了出去。并且在出现很多行“Result:”之后该过程停止了(变量“line”为空)。

在打印后删除

if line:
并添加
time.sleep(0.5)
(记住
import time
!)会显示相同的结果。

所以解决办法是:家长必须等待孩子。


0
投票

您的命令在返回之前首先等待子进程完成。尝试在 Popen 中使用

start_new_session=True
选项。

© www.soinside.com 2019 - 2024. All rights reserved.