Python 的日志模块有啥进程不安全?

2020-04-12  本文已影响0人  JenningLang

很早以前有一位老同事和我说 Python 日志模块多进程不安全,没办法多个进程同时写一个日志文件。当时只是看了一下 官方文档 确实明确的说是 Thread Safe,就也没有深究这个问题。

这几天正好看一个项目里用了 ConcurrentLogHandler 包,忽然想仔细看一下 Python 日志模块到底在多进程下有啥问题。

TL;DR;

上面说的正常情况下,是指 Handle 初始化的时候模式要用默认的 mode='a'

1. 正常情况下,如果不做日志 Rotate,不会有任何问题

Python 的 logging.FileHandler 日志读写依赖的是什么?如果看过 logging.FileHandler日志模块的源码就知道该模块在初始化的时候会调用 open 打开一个文件输出流,每次写日志就是 write + flush 的过程。

def emit(self, record):
    try:
        msg = self.format(record)
        stream = self.stream
        stream.write(msg)
        stream.write(self.terminator)
        self.flush()
    except Exception:
        self.handleError(record)

而我们知道,python 在写文件的过程中,如果是通过 mode='a' 打开的文件,多进程写文件不会出现任何问题(见文末参考),所以,mode='a' 的情况下,多进程同时写日志文件不会出现任何问题

2. 如果多进程 Rotate 日志文件,会出问题

但是如果多个进程同时 Rotate 文件,就会出现问题。

一个典型的 case 是一个进程已经 Rotate 并写入 Rotate 后的文件了;
另一个进程此时恰巧进行 Rotate,就会删掉第一次创建的新文件,这期间第一个进程写入的日志就会丢失。

网上还有人说发现了特定情况下,同时写新旧两个日志文件的情况,这个我也没有遇到过,暂时也没有脑细胞分析会不会出现这种情况

3. 如何解决

相关的解决办法网上已经很多了,也不是本文讨论的重点,例如:

备注:

A. ConcurrentLogHandler 的作用

我们可以看一下该模块官方文档是怎么说的:

Python logging handler that allows multiple processes to safely write to the same log file concurrently. This module extends the standard RotatingFileHandler functionality, and can be use as a drop-in replacement for that logging class.

Python 官方的 logging handler 允许多进程对日志文件的安全读写。本模块扩展了 RotatingFileHandler 的功能,可以用来直接替换原来的 RotatingFileHandler

B. 更多参考

上一篇 下一篇

猜你喜欢

热点阅读