python多线程下logging错乱主因是streamhandler的write/flush非原子操作;解决方案首选queuehandler+queuelistener单线程消费,其次显式指定encoding、避免重复初始化。
Python 多线程下 logging 默认不是线程安全的——但你不用手动加锁,只要配置得当,错乱问题就能消失。
为什么多线程日志会错乱
根本原因不是 logging 模块本身不支持并发,而是多个线程同时调用 handler.emit() 时,若 handler 是 StreamHandler(比如输出到 sys.stdout),底层的 write() 和 flush() 操作可能被交叉执行,导致日志行粘连、截断或顺序颠倒。
常见现象包括:
- 两行日志内容挤在同一行,比如
"INFO:root:task1 start\nINFO:root:task2 done"变成"INFO:root:task1 startINFO:root:task2 done" - 日志头(时间、级别、模块名)和消息体分离,比如
"INFO:root: task2 finished"中的冒号后空格被切到下一行 - 使用
RotatingFileHandler时出现IOError: [Errno 9] Bad file descriptor(尤其在频繁重开文件时)
用 logging.getLogger() + StreamHandler 配合 Lock 就够了
logging 的 Logger 对象本身是线程安全的(内部用了 threading.RLock),真正需要保护的是 Handler 的 emit()。但多数场景下,你不需要自己写 Lock——直接用标准库自带的 QueueHandler + QueueListener 组合,才是最稳妥的解法。
立即学习“Python免费学习笔记(深入)”;
实操建议: