Linux下Python脚本重定向输出顺序颠倒及实时输出方案咨询
Python子进程输出顺序异常问题解析
问题场景
我有两个运行在Linux系统下的Python脚本:
test.py
#!/usr/bin/env python3 import subprocess print('first line') subprocess.run('./test_1.py', shell=True, encoding='utf-8')
test_1.py
#!/usr/bin/env python3 print('second line')
直接执行./test.py时,输出顺序正常:
first line second line
但执行./test.py > test将输出重定向到文件后,文件内容顺序颠倒:
second line first line
我尝试调整subprocess.stdout、subprocess.stderr、sys.stdout和sys.stderr参数,都没解决问题。
有一种方式能保证输出顺序,但会延迟子脚本输出:
#!/usr/bin/env python3 import subprocess print('first line') text = subprocess.run('./test_1.py', stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=True, encoding='utf-8') print(text.stdout)
这种方式要等test_1.py执行完才会打印其输出,无法实时查看长耗时脚本的运行过程。
我的问题:
- 为什么两种运行方式下输出顺序不同?
- 是否能在以下两种场景中,既保证输出顺序正确又实时获取子脚本输出?
./test.py./test.py > test
问题解答
1. 输出顺序颠倒的原因
这是Python标准输出的缓冲机制导致的:
- 当输出直接指向终端时,Python默认使用行缓冲模式,
print('first line')会立即把内容刷到终端,所以先显示first line,再执行子进程输出second line。 - 当输出被重定向到文件时,Python切换为全缓冲模式,
print('first line')的内容会先存在缓冲区里,不会立刻写入文件。此时子进程test_1.py的输出通过shell直接写入文件(它的缓冲规则在重定向时也会变化,且子进程执行更快),导致second line先被写入,而父进程的first line要等到脚本结束或缓冲区满才会被刷入,最终顺序颠倒。
2. 实时且有序输出的解决方案
以下两种方案可同时满足终端和文件重定向场景的实时、有序输出:
方案一:强制父进程使用行缓冲/无缓冲
在父进程中修改标准输出的缓冲模式,确保print内容立即输出:
#!/usr/bin/env python3 import subprocess import sys # 强制设置标准输出为行缓冲模式 sys.stdout = open(sys.stdout.fileno(), 'w', buffering=1) print('first line') subprocess.run('./test_1.py', shell=True, encoding='utf-8')
或者执行脚本时使用Python的-u参数(强制无缓冲):
python3 -u ./test.py > test
方案二:手动刷新父进程缓冲区+子进程继承输出流
手动刷新父进程的输出缓冲区,同时让子进程继承父进程的标准输出流:
#!/usr/bin/env python3 import subprocess import sys print('first line') sys.stdout.flush() # 手动刷新,确保内容先写入输出目标 # 让子进程直接使用父进程的stdout/stderr subprocess.run('./test_1.py', shell=True, encoding='utf-8', stdout=sys.stdout, stderr=sys.stderr)
这种方式下,first line会在子进程启动前就被写入输出目标,子进程的输出也会实时同步,无论终端还是文件重定向都能保持顺序。
内容的提问来源于stack exchange,提问作者Pro
相关产品推荐
相关产品推荐

