Python 的日誌模塊有啥進程不安全?

很早以前有一位老同事和我說 Python 日誌模塊多進程不安全,沒辦法多個進程同時寫一個日誌文件。當時只是看了一下 官方文檔 確實明確的說是 Thread Safe,就也沒有深究這個問題。

這幾天正好看一個項目裏用了 ConcurrentLogHandler 包,忽然想仔細看一下 Python 日誌模塊到底在多進程下有啥問題。

TL;DR;

  • 正常情況下,如果不做日誌 Rotate,不會有任何問題
  • 如果多進程 Rotate 日誌文件,會出問題
  • 這一切都和讀寫文件沒什麼關係

上面說的正常情況下,是指 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. 更多參考

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章