Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/338.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
python子进程赢得';t像终端那样交错stderr和stdout_Python_Python 3.x_Subprocess - Fatal编程技术网

python子进程赢得';t像终端那样交错stderr和stdout

python子进程赢得';t像终端那样交错stderr和stdout,python,python-3.x,subprocess,Python,Python 3.x,Subprocess,测试程序 #/usr/bin/env蟒蛇3 导入系统 计数=0 sys.stderr.write('stderr,订单%d\n“%count”) 计数+=1 sys.stdout.write('stdout,订单%d\n“%count”) 计数+=1 sys.stderr.write('stderr,订单%d\n“%count”) 计数+=1 sys.stdout.write('stdout,订单%d\n“%count”) 通过终端调用时,预期输出为 stderr, order 0 stdou

测试程序

#/usr/bin/env蟒蛇3
导入系统
计数=0
sys.stderr.write('stderr,订单%d\n“%count”)
计数+=1
sys.stdout.write('stdout,订单%d\n“%count”)
计数+=1
sys.stderr.write('stderr,订单%d\n“%count”)
计数+=1
sys.stdout.write('stdout,订单%d\n“%count”)
通过终端调用时,预期输出为

stderr, order 0
stdout, order 1
stderr, order 2
stdout, order 3
在交互式shell中,当我将
stdout
重定向到管道时,输出顺序与上面的输出不同,在上面的输出中,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
是行缓冲的,否则它的块会被缓冲,并且只有在命中某个块边界时才会刷新到文件描述符。当您重定向到管道时,流不再是tty,块缓冲生效

解决方案是重新打开
stdout
,指定您希望不考虑行缓冲(1)。在C级,
stderr
始终是行缓冲的,但当我测试时,只是重新打开
stdout
程序就好像
stderr
是块缓冲的。我很惊讶。也许这是中间的
io.TextIO
层或者其他一些奇怪的东西,但是我发现我需要修复这两个管道

即使
stdout
stderr
进入同一管道,但就执行的程序而言,它们是具有独立缓冲区的独立文件描述符。这就是为什么即使在块模式下,交错也不会在输出缓冲区中自然发生

#!/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)