发布于2026-04-19 阅读(0)
扫一扫,手机访问
多进程下logging日志乱序或丢失是因为FileHandler非进程安全,多个进程同时写文件导致覆盖或截断;推荐用QueueHandler+QueueListener由主进程统一落盘,或使用concurrent_log_handler加文件锁。

logging 为什么日志会乱序或丢失因为默认的 FileHandler 不是进程安全的——多个子进程同时写同一个文件,底层 write() 调用可能被内核打断,导致内容覆盖、截断或错行。不是“没打印”,而是写坏了。
RotatingFileHandler 切割后部分日志消失;同一时间戳出现两条不连贯的日志;日志里突然夹着半句话logging 模块本身不处理跨进程同步,FileHandler 底层调用的是 C 标准库的 fwrite 或系统 write,无锁threading.Lock 解决——它只管线程,不管进程QueueHandler + QueueListener 是最稳的方案让所有子进程把日志发到一个 multiprocessing.Queue,由主进程里的监听器统一落盘。这是官方推荐路径,也绕开了文件锁难题。
QueueHandler,把日志塞进队列,不碰文件QueueListener,绑定真实的 FileHandler 或 RotatingFileHandler,负责消费和写入multiprocessing.Manager().Queue() 或在 Process 启动前创建好再传入queue = multiprocessing.Queue()
handler = logging.FileHandler("app.log")
listener = logging.handlers.QueueListener(queue, handler)
listener.start()
# 子进程中:
logger.addHandler(logging.handlers.QueueHandler(queue))
concurrent_log_handler 可以省事,但得知道它怎么锁这个第三方包用文件级 flock 实现进程互斥,比自己手写队列轻量,适合快速落地,但有隐藏约束。
msvcrt.locking,行为略有差异)"logs/app.log",而各进程工作目录不同,就等于在写不同文件FileHandler 即可:from concurrent_log_handler import ConcurrentRotatingFileHandler
handler = ConcurrentRotatingFileHandler("app.log", "a", 512*1024, 5)
logging.basicConfig()它会偷偷新建 StreamHandler 并绑定到根 logger,不仅污染主进程配置,还可能和主进程的 QueueListener 冲突,导致日志重复或静默丢弃。
logging.getLogger("myapp"),不新建 handlerQueueHandler 绑定)后再启动子进程spawn 启动方式(macOS/Linux 默认),子进程不会继承主进程的 logger 配置,这点比 fork 更容易出问题print(logger.handlers) 看子进程里到底挂了啥 handler,比猜快得多实际部署时最容易忽略的是子进程的 logger 名称一致性——名称不同就拿不到主进程配好的 QueueHandler,日志直接走默认的 NullHandler,悄无声息地消失。
上一篇:爱去小说网漫画入口位置详解
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
正版软件
正版软件
正版软件
正版软件
正版软件
1
2
3
7
8