簡體   English   中英

Python多處理+ logging.FileHandler

[英]Python multiprocessing+logging.FileHandler

我正在嘗試在多處理服務器中實現日志記錄。 根據文檔,“不支持從多個進程記錄到單個文件”。 我創建了一個小程序來檢查這個語句:

import logging
import multiprocessing
import os

log = logging.getLogger()


def setup_logger():
    formatter = logging.Formatter('%(asctime)s %(name)s %(levelname)s: %(message)s')

    fileHandler = logging.FileHandler('test.log')
    fileHandler.setFormatter(formatter)

    log.setLevel(logging.DEBUG)
    log.addHandler(fileHandler)


def write_log_entries(identifier, start_event):
    start_event.wait()
    for i in range(100):
        s = ''.join(str(identifier) for k in range(30))
        log.info('[{}, {}] --- {}'.format(os.getpid(), identifier, s))


if __name__ == '__main__':
    setup_logger()
    procs = []
    start_event = multiprocessing.Event()
    for i in range(100, 300):
        p = multiprocessing.Process(target=write_log_entries, args=(i, start_event))
        procs.append(p)

    for p in procs:
        p.start()

    start_event.set()

    for p in procs:
        p.join()

在執行上面的代碼后,我希望在“test.log”中看到一個完整的混亂,但一切似乎都很好(當然,時間戳除外,它們不是按順序)。

任何人都可以解釋為什么當多個進程同時寫入日志文件時,日志條目是否重疊? 在這種情況下,log.info()可以被認為是原子的嗎?

簡短的回答:內核鎖定單個調用write ,所以只要消息很小就可以,所以只需一次write就可以刷新,這樣write就能成功寫入所有內容。 沒有一般保證是這種情況,這就是為什么文檔不承諾這將工作的原因。

答案很長:每次調用log.info刷新日志輸出。 這是必要的,否則您將無法在文件中看到最新的日志條目。 在Python / libc級別,flush實現為對write(2)系統調用的調用,調用該調用以寫出文件緩沖區的內容(如果有)。 在您的情況下,緩沖區內容是您的日志消息。 因此,Python或libc(取決於正在使用的文件)最終會調用OS調用,例如:

write(fd, buf, buflen);

...其中fd是日志文件的系統級文件描述符, buf是寫入緩沖的內存, buflen是消息的長度。 (如果使用諸如Linux上的strace的工具跟蹤Python進程,則可以看到這些調用。) write返回成功寫入的字符數,並且內核不會將這些字符與文件的同一區域中的其他寫入交錯。 如果在O_APPEND模式下打開文件,則寫入甚至保證在文件末尾,至少在Unix上。 因此,如果buflen很小,就像普通日志消息一樣,一切都很好。 但至少有兩件事可能出錯。

首先,不能保證所有buflen都將在一次write write可以被信號中斷, fd可以指向接受固定大小寫入的設備,或者您的日志消息可能足夠大,內核不能在單個塊中接受它。 通常情況下,這不是問題 - 正確寫入的write總是作為循環實現。 但在你的情況下,這將是一場災難,因為不同的write調用與其他進程交錯。

其次,如果您的日志消息足夠大以至於它不適合stdio緩沖區(8K左右),那么它將在到達內核之前被拆分為塊。 在記錄回溯時,或將日志格式化為XML等詳細格式時,很容易發生這種情況。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM