gpt4 book ai didi

python子进程不会像终端那样交错stderr和stdout

转载 作者:行者123 更新时间:2023-12-03 23:49:10 26 4
gpt4 key购买 nike

一个测试程序

#!/usr/bin/env python3

import sys

count = 0
sys.stderr.write('stderr, order %d\n' % count)
count += 1
sys.stdout.write('stdout, order %d\n' % count)
count += 1
sys.stderr.write('stderr, order %d\n' % count)
count += 1
sys.stdout.write('stdout, order %d\n' % count)

当通过终端调用时,预期的输出是,
stderr, order 0
stdout, order 1
stderr, order 2
stdout, order 3

在交互式 shell 中,当我重定向 stdout 时对于 PIPE,输出顺序与上面的输出不同,其中 Popen 将分组 stderr并将它们全部写入,然后对 stdout 执行相同的操作, 而不是交错 stdout 和 stderr。
In [29]: a = sp.run(['./test.py'], stderr=sp.STDOUT)
stderr, order 0
stdout, order 1
stderr, order 2
stdout, order 3

In [30]: a
Out[30]: CompletedProcess(args=['./test.py'], returncode=0)

In [33]: b = sp.Popen(['./test.py'], stderr=sp.STDOUT, stdout=sp.PIPE, encoding='utf-8')

In [34]: print(b.communicate()[0])
stderr, order 0
stderr, order 2
stdout, order 1
stdout, order 3

最佳答案

在 C 库(以及基于 c 的 python)中,流的处理方式不同,具体取决于它们是否连接到交互式终端(或假装的东西)。对于 tty , stdout是行缓冲的,否则它的块被缓冲并且只有在遇到某个块边界时才刷新到文件描述符。当您重定向到 PIPE 时,流不再是 tty 并且块缓冲生效。

解决办法是重新打开stdout指定无论如何都需要行缓冲 (1)。 C级,stderr总是行缓冲,但当我测试时只是重新打开 stdout该程序就像 stderr是块缓冲的。我很惊讶。也许这是中间的io.TextIO层或其他一些奇怪的东西,但我发现我需要修复两个管道。

即使 stdoutstderr转到同一个管道,就执行的程序而言,它们是具有单独缓冲区的单独文件描述符。这就是为什么即使在块模式下也不会在输出缓冲区中自然发生交错的原因。

#!/usr/bin/env python3

import sys
import os

# reopen stdout line buffered
sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', 1)

# this surprises me, seems like we have to reopen stderr
# line buffered, but i thought it was line buffered anywy.
# perhaps its the intermediate python TextIO layer?
sys.stderr = os.fdopen(sys.stderr.fileno(), 'w', 1)

count = 0
sys.stderr.write('stderr, order %d\n' % count)
count += 1
sys.stdout.write('stdout, order %d\n' % count)
count += 1
sys.stderr.write('stderr, order %d\n' % count)
count += 1
sys.stdout.write('stdout, order %d\n' % count)

关于python子进程不会像终端那样交错stderr和stdout,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60253459/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com