如何让Python脚本输出实时写入日志并区分运行进程?
解决Python脚本输出实时写入日志+区分进程的问题
问题根源
Python默认对标准输出(stdout)采用块缓冲:输出到终端时是行缓冲(实时显示),但重定向到文件时会攒够一块数据才写入,导致只有脚本运行结束后才会看到日志内容。而python3 -u虽能强制行缓冲实现实时写入,但所有Python进程名都显示为python3,用killall这类命令批量管理时容易误杀其他Python进程。
解决方案
方案1:修改脚本,强制实时刷新输出
无需依赖特殊命令行参数,直接在脚本内控制输出缓冲,用普通重定向命令即可:
- 方法A:给
print添加flush=True参数
修改后的test.py:
#!/usr/bin/python3 from time import sleep for i in range(0,21): print(i, flush=True) # 每次打印后立即刷新缓冲区 sleep(1)
启动命令:./test.py > test.log 2>&1 &
- 方法B:全局设置stdout为行缓冲
在脚本开头添加以下代码,开启全局行缓冲,每次换行自动刷新:
import sys sys.stdout.line_buffering = True
同样用普通重定向命令即可实现实时写入。
方案2:用stdbuf命令强制行缓冲(无需修改脚本)
stdbuf可以从外部控制程序的标准IO缓冲模式,不用改脚本就能实现实时输出:
stdbuf -oL ./test.py > test.log 2>&1 &
参数说明:
-oL:将stdout设置为行缓冲- 如果需要stderr也实时写入,加上
-eL参数即可
方案3:自定义进程名,方便批量管理
如果需要保留-u的实时效果,同时让进程名可区分,用exec -a修改进程的显示名称:
exec -a test_script python3 -u test.py > test.log 2>&1 &
此时用ps aux | grep test_script就能看到自定义的进程名,批量杀死时直接执行:
killall -9 test_script
原理:exec -a会修改进程的argv[0],让ps、killall等工具识别为你指定的名称,完全不影响脚本运行逻辑。
补充:通过PID精准管理进程(通用方法)
不管用哪种方案,都可以通过记录PID来精准控制进程:
- 启动脚本时同步记录PID:
./test.py > test.log 2>&1 & echo $! > test.pid
- 杀死进程时直接读取PID:
kill -9 $(cat test.pid)
内容的提问来源于stack exchange,提问作者Daniel L.
相关产品推荐
相关产品推荐

