问题描述
由于不用配置过多配置信息,想通过nohup打印django项目的console控制台的日志,最后调试的时候发现nohup.out始终不能实时看到console的print信息,但又有部分日志能看到,比如错误日志
原因查找
原来python解释器中,print是stdout输出, stdout输出流默认是行缓存的 ( line-buffered ),重定向和输出到控制台的内容会先被存在缓冲区中暂存,遇到换行符“\n”,或者缓存区的数据满 4k,才会将内容写到重定向的文件或者控制台中去。stderr不会先输出到缓冲区,所以才看到nohup 没有及时日志的原因而错误日志能实时输出。(但3.9版本后也变成了行缓存,可以见https://github.com/python/cpython/commit/d17f3d8315a3a775ab0807fc80acf92b1bd682f8)
可以通过按ctrl+c的方式试验,不过不要用kill,kill的时候日志信息就丢了
解决
方法一:直接加个环境变量,永久生效需要加到环境变量配置里
export PYTHONUNBUFFERED=1
nohup xxx
方法二:加个-u参数
nohup python -u xxxx
方法三:加代码,在print后加上
print ("print")
import sys
sys.stdout.flush()
方法四:print后加上flush参数,默认为参数
print ("print",flush=true)
由于本人使用的是nohup gunicorn,则使用第一种方式最为合适。配置好后,既可以看到实时日志
深入思考
从官网的资料说明来看,交互模式下,stdout是行输出,也就是为什么python3中,我们输入print后能直接打印显示,而python2却不行。因为print在python3中是函数,默认带换行符。换行符也就会将缓冲区的数据打印出来,这样也就说的通了。
脚本验证如下:python3是一行行输出,而python2是跑完,全部输出
import time
import sys
for i in range(5):
print(i)
#sys.stdout.flush()
time.sleep(20)
但官网只说明python3中只有交互模式下是行缓冲,而其他模式是块缓冲(就是一次性输出)
When interactive, the stdout stream is line-buffered. Otherwise, it is block-buffered like regular text files. The stderr stream is line-buffered in both cases. You can make both streams unbuffered by passing the -u command-line option or setting the PYTHONUNBUFFERED environment variable
但问题是python3中怎样算交互模式?望有大佬解释
python3 ss.py 一行行输出
python3 ss.py >> 22.txt 一次性输出。重定向输出
nohup python3 ss.py 一次性输出。重定向输出