python subprocess:使用subprocess.PIPE时输出顺序的变化

时间:2016-09-27 11:25:59

标签: python pipe subprocess python-3.5

当我编写一个名为outer.py的包含

的python脚本时
p = subprocess.Popen(['./inner.py'])
print('Called inner.py without options, waiting for process...')
p.wait()
print('Waited for inner.py without options')

p = subprocess.Popen(['./inner.py'], stdout=subprocess.PIPE)
print('Called inner.py with PIPE, communicating...')
b_out, b_err = p.communicate()
out = b_out.decode('utf8')
print('out is "{}"'.format(out))

包含<{p}的inner.py

print("inner: Echoing Hallo")
p = subprocess.Popen(['echo', 'hallo'])
print("inner: Waiting for Echo to finish...")
p.wait()
print("inner: Waited for Echo")

从终端呼叫outer.py时,我收到以下信息:

Called inner.py without options, waiting for process...
inner: Echoing Hallo
inner: Waiting for Echo to finish...
hallo
inner: Waited for Echo
Waited for inner.py without options

Called inner.py with PIPE, communicating...
out is "hallo
inner: Echoing Hallo
inner: Waiting for Echo to finish...
inner: Waited for Echo
"

为什么在用inner.py调用stdout=subprocess.PIPE时,“hallo”是否出现在捕获输出中的“inner:Echoing Hallo”之前?

1 个答案:

答案 0 :(得分:3)

我猜想,出于某种原因(与管道与ttys相关,请参阅this comment),inner.py Python进程的输出在您第一次调用它时是无缓冲的,并且缓冲了第二次你打电话。第一次,使用无缓冲输出,您将获得写入tty的预期顺序的结果。第二次,通过缓冲,echo命令的输出首先被刷新(因为echo运行并终止),然后inner.py进程的所有输出立即显示,当python终止时。如果禁用inner.py的输出缓冲,则在两种情况下都应获得相同的输出。

通过设置PYTHONUNBUFFERED环境变量,或使用-u开关调用python,或在每sys.stdout.flush()之后显式调用print(或{{}来禁用输出缓冲1)}在Python 3)上。

管道和ttys的行为之间的区别似乎是general behaviour of stdio:输出到ttys是行缓冲的(所以,在你的代码中,它逐行读取,它似乎是无缓冲的),而管道的输出是缓冲的。