Hei*_*ing 75 python subprocess
我正在使用Python subprocess.communicate()
来从一个运行大约一分钟的进程中读取stdout.
如何stdout
以流式方式打印出该流程的每一行,以便我可以看到生成的输出,但在继续之前仍然阻止流程终止?
subprocess.communicate()
似乎立刻提供所有输出.
jfs*_*jfs 143
一旦子进程刷新其stdout缓冲区,就要逐行获取子进程的输出:
#!/usr/bin/env python2
from subprocess import Popen, PIPE
p = Popen(["cmd", "arg1"], stdout=PIPE, bufsize=1)
with p.stdout:
for line in iter(p.stdout.readline, b''):
print line,
p.wait() # wait for the subprocess to exit
Run Code Online (Sandbox Code Playgroud)
iter()
用于在编写行时立即读取行以解决Python 2中的预读错误.
如果子进程'stdout在非交互模式下使用块缓冲而不是行缓冲(这会导致输出延迟,直到子缓冲区已满或由子进程显式刷新),那么您可以尝试强制使用无缓冲输出 pexpect
,pty
模块或unbuffer
,stdbuf
,script
公用事业,见问:为什么不直接使用管道(POPEN())?
这是Python 3代码:
#!/usr/bin/env python3
from subprocess import Popen, PIPE
with Popen(["cmd", "arg1"], stdout=PIPE, bufsize=1,
universal_newlines=True) as p:
for line in p.stdout:
print(line, end='')
Run Code Online (Sandbox Code Playgroud)
注意:与Python 2不同,它按原样输出子进程'bytestrings; Python 3使用文本模式(cmd的输出使用locale.getpreferredencoding(False)
编码解码).
unu*_*tbu 41
请注意,我认为JF Sebastian的方法(下面)更好.
这是一个简单的例子(没有检查错误):
import subprocess
proc = subprocess.Popen('ls',
shell=True,
stdout=subprocess.PIPE,
)
while proc.poll() is None:
output = proc.stdout.readline()
print output,
Run Code Online (Sandbox Code Playgroud)
如果ls
结束太快,则while循环可能在您读取所有数据之前结束.
您可以通过这种方式捕获stdout中的剩余部分:
output = proc.communicate()[0]
print output,
Run Code Online (Sandbox Code Playgroud)
我相信以流方式从流程中收集输出的最简单方法是这样的:
import sys
from subprocess import *
proc = Popen('ls', shell=True, stdout=PIPE)
while True:
data = proc.stdout.readline() # Alternatively proc.stdout.read(1024)
if len(data) == 0:
break
sys.stdout.write(data) # sys.stdout.buffer.write(data) on Python 3.x
Run Code Online (Sandbox Code Playgroud)
该readline()
或read()
函数只应在EOF返回一个空字符串,进程终止后-否则,如果没有什么阅读(它会阻止readline()
包括换行,等空行,则返回"\n").这避免了communicate()
在循环之后需要进行尴尬的最终调用.
对于具有很长行的文件read()
可能更可取,以减少最大内存使用量 - 传递给它的数量是任意的,但排除它会导致一次读取整个管道输出,这可能是不可取的.
归档时间: |
|
查看次数: |
72804 次 |
最近记录: |