Python子进程输出顺序颠倒及终端与日志同步打印问题求解
解决Python子进程输出顺序颠倒与实时打印问题
问题背景
拥有两个Python文件main.py和main_test.py,main.py通过os.system调用main_test.py:
- 直接运行时输出顺序正常;
- 执行
main.py > log将输出重定向到日志文件时,输出顺序颠倒; - 执行
python3 main.py | tee log同时打印到终端和日志时,终端需等待执行完成才输出,且顺序仍颠倒。
需要解决两个问题:
- 修复输出顺序颠倒的问题;
- 实现终端实时打印结果且日志记录顺序正确。
复现用的原始代码:
main.py
import os import time import datetime import pytz python_file_name = 'main_test'+'.py' time_zone = pytz.timezone('US/Eastern') # Eastern-Time-Zone curr_time = datetime.datetime.now().replace(microsecond=0).astimezone(time_zone).time() print(f'Main file: {curr_time}') cwd = os.path.join(os.getcwd(), python_file_name) os.system(f'python3 {cwd}')
main_test.py
import pytz import datetime import time time_zone = pytz.timezone('US/Eastern') # Eastern-Time-Zone for i in range(3): curr_time = datetime.datetime.now().replace(microsecond=0).astimezone(time_zone).time() print(f'Executed file: {curr_time}') time.sleep(1)
问题原因
Python的标准输出缓冲机制导致:
- 输出到终端时采用行缓冲,每行打印后自动刷新;
- 输出到文件或管道时采用块缓冲,只有缓冲区满或进程结束时才会写入。
主进程的print内容先产生但未立即刷新,子进程的输出先被写入文件/管道,最终导致顺序颠倒;tee因管道缓冲,需等待进程结束才会把内容输出到终端。
解决方案
1. 修复输出顺序颠倒
有两种核心思路,任选其一或组合使用:
方法一:强制刷新每个print的缓冲区
在所有print语句中添加flush=True参数,强制立即输出内容:
修改后的main.py:
import os import time import datetime import pytz python_file_name = 'main_test'+'.py' time_zone = pytz.timezone('US/Eastern') # Eastern-Time-Zone curr_time = datetime.datetime.now().replace(microsecond=0).astimezone(time_zone).time() # 强制刷新缓冲区 print(f'Main file: {curr_time}', flush=True) cwd = os.path.join(os.getcwd(), python_file_name) os.system(f'python3 {cwd}')
修改后的main_test.py:
import pytz import datetime import time time_zone = pytz.timezone('US/Eastern') # Eastern-Time-Zone for i in range(3): curr_time = datetime.datetime.now().replace(microsecond=0).astimezone(time_zone).time() # 强制刷新缓冲区 print(f'Executed file: {curr_time}', flush=True) time.sleep(1)
方法二:运行Python时禁用缓冲
使用python3 -u参数启动Python,强制标准输出无缓冲:
- 调用子进程时添加
-u:os.system(f'python3 -u {cwd}'); - 运行主进程时也添加
-u:python3 -u main.py > log。
2. 实现终端实时打印+日志顺序正确
结合上述方法,同时确保主进程和子进程的输出无缓冲,再配合tee命令即可实现:
步骤:
- 按方法一修改两个文件的
print语句添加flush=True,或按方法二在子进程调用时用python3 -u; - 执行命令:
python3 -u main.py | tee log
(-u确保主进程输出无缓冲,配合子进程的无缓冲设置,tee就能实时将内容输出到终端并写入日志)
内容的提问来源于stack exchange,提问作者Saeed
相关产品推荐
相关产品推荐

