Python脚本在crontab与终端运行时print和logging输出顺序相反
输出顺序反转问题原因说明
核心原因是Python标准输出(stdout)和标准错误(stderr)的缓冲机制差异,具体解释如下:
- 首先明确两个输出的目标流:
print()函数默认输出到stdout(标准输出流),logging库的ERROR级别日志默认输出到stderr(标准错误流)。 - 交互式终端运行时的缓冲逻辑:当输出目标是交互式终端时,
stdout默认采用行缓冲策略,遇到换行符就会立即把缓冲区内容刷到输出设备,print输出的内容自带换行符,因此会直接打印,之后才执行logging输出到无缓冲的stderr,顺序符合代码执行顺序。 - crontab非交互式运行时的缓冲逻辑:当输出目标不是交互式终端(crontab执行时输出会先缓存最后拼成邮件),
stdout会切换为全缓冲策略,只有缓冲区满、或者进程退出时才会把缓冲区内容统一写出;而stderr默认始终是无缓冲策略,只要有内容就立即写出。因此脚本执行时,logging的错误日志会直接输出,而print的内容暂存在stdout缓冲区,直到脚本运行结束进程退出时才被写出,最终就出现了输出顺序反转的情况。
解决方案
如果要避免该问题,可以用以下任意一种方式:
- 调用
print时主动开启强制刷缓冲:print('normal print', flush=True) - 执行Python脚本时添加
-u参数,禁用stdout/stderr的缓冲机制,crontab规则修改为:25 10 * * * python3 -u ~/test.py - 导入sys模块后,在print语句后手动调用
sys.stdout.flush()主动刷新标准输出缓冲区。
内容的提问来源于stack exchange,提问作者martin-h
相关产品推荐
相关产品推荐

