【问题标题】:python subprocess: order of output changes when using subprocess.PIPEpython subprocess:使用subprocess.PIPE时输出顺序发生变化
【发布时间】:2017-02-05 00:18:57
【问题描述】:

当我编写一个名为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))

还有一个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
"

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

【问题讨论】:

  • 无法在我的 Mac 上重现 - 但是我必须首先添加 shebang 和 import 语句才能使代码正常工作。请提供完整的示例以及您使用的操作系统。
  • 听起来它可能在标准 outner.py 上缓冲。您可以尝试禁用缓冲,例如设置 PYTHONUNBUFFERED 吗?此处列出了更多技术:stackoverflow.com/a/107717/1062499
  • 传达不是单循环动作并且总是返回字符串,而不是输出!
  • @wildwilhelm 你是对的,当我禁用输出缓冲时,输出的显示顺序与脚本中相应语句的顺序相同。但是为什么根据从 external.py 调用 inner.py 的方式不同,行为会有所不同?

标签: python pipe subprocess python-3.5


【解决方案1】:

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

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-02-02
    • 1970-01-01
    • 1970-01-01
    • 2014-02-16
    • 2021-12-15
    • 2011-09-22
    • 2023-03-12
    • 1970-01-01
    相关资源
    最近更新 更多