Python 中如何把日志输出到标准输出(stdout)?
Python logging 默认输出到 stderr。输出到 stdout 需要显式创建 StreamHandler(sys.stdout)。本文介绍配置方法及容器环境的最佳实践。
Python 的 logging 默认输出到 stderr。要输出到 stdout,创建 StreamHandler(sys.stdout) 显式指定。
快速方式
import logging
import sys
logging.basicConfig(stream=sys.stdout, level=logging.INFO)
logging.info("这条日志输出到 stdout")
basicConfig 的 stream 参数默认是 sys.stderr,显式传入 sys.stdout 即可切换。
手动配置(更灵活)
import logging
import sys
logger = logging.getLogger("my_app")
handler = logging.StreamHandler(sys.stdout)
handler.setFormatter(logging.Formatter('%(asctime)s [%(levelname)s] %(message)s'))
logger.addHandler(handler)
logger.setLevel(logging.INFO)
logger.info("Hello, stdout!")
为什么容器环境推荐输出到 stdout
Docker/K8s 环境中,应用应该把日志输出到 stdout/stderr,由容器运行时(Docker 的 json-file 驱动)收集,再由日志采集工具统一收集——而不是写文件。原因:
- 容器文件系统是临时的,容器删除后日志文件丢失;
- stdout 日志天然支持
docker logs查看; - 采集工具(DataKit、Fluentd 等)统一从 stdout 收集。
观测云对照
观测云 DataKit 在 K8s 环境以 DaemonSet 部署,自动采集所有容器的 stdout/stderr 日志,不需要应用做任何文件配置。应用只需确保日志输出到 stdout 即可。
常见问题(FAQ)
Q:stdout 和 stderr 输出有区别吗?
A:功能上都可以被采集工具收集。约定俗成:正常日志走 stdout,错误走 stderr。K8s 环境下两者都会被收集。
Q:print 和 logging 输出到 stdout 有什么区别?
A:print 是裸输出,logging 带格式(时间、级别、模块名)、级别控制、多 Handler 路由。生产代码应该用 logging。
Q:Docker 里日志延迟出现?
A:Python 的 stdout 在管道模式下是块缓冲。加 PYTHONUNBUFFERED=1 环境变量或 python -u 运行即可解决。