亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

如何在 Python 中分離日志處理程序

如何在 Python 中分離日志處理程序

手掌心 2022-06-02 12:05:59
我有一種情況,我想在 Python 中創建兩個單獨的記錄器對象,每個對象都有自己獨立的處理程序?!胺蛛x”是指我希望能夠獨立地將日志語句傳遞給每個對象,而不會污染其他日志。主文件import loggingfrom my_other_logger import init_other_loggerlogger = logging.getLogger(__name__)logging.basicConfig(level=logging.INFO, handlers=[logging.StreamHandler(sys.stdout)])other_logger = init_other_logger(__name__)logger.info('Hello World') # Don't want to see this in the other loggerother_logger.info('Goodbye World') # Don't want to see this in the first loggermy_other_logger.pyimport loggingimport os, sysdef init_other_logger(namespace):    logger = logging.getLogger(namespace)    logger.setLevel(logging.DEBUG)    fh = logging.FileHandler(LOG_FILE_PATH)    logger.addHandler(fh)    formatter = logging.Formatter('%(levelname)s:%(name)s:%(message)s')    fh.setFormatter(formatter)    #logger.propagate = False    return logger我能夠確定在這里有用的唯一配置是logger.propagate屬性。按原樣運行上面的代碼將所有日志語句通過管道傳輸到日志流和日志文件。當我沒有logger.propagate = False任何東西被傳送到日志流時,兩個日志對象再次將它們的輸出傳送到日志文件。如何創建一個僅將日志發送到一個處理程序的日志對象,以及另一個將日志發送到另一個處理程序的日志對象?
查看完整描述

2 回答

?
繁花不似錦

TA貢獻1851條經驗 獲得超4個贊

首先,讓我們先看看發生了什么,然后再著手解決問題。


logger = logging.getLogger(__name__) :當你這樣做時,你正在獲取或創建一個名為'main'. 由于這是第一次調用,它將創建該記錄器。


other_logger = init_other_logger(__name__): 當你這樣做時,你再次獲取或創建一個名為 的記錄器'main'。由于這是第二次調用,它將獲取上面創建的記錄器。所以你并沒有真正實例化一個新的記錄器,但是你得到了對上面創建的同一個記錄器的引用。您可以在調用init_other_logger表格后通過打印來檢查這一點:) print(logger is other_logger。


接下來發生的事情是將 aFileHandler和 a添加Formatter到'main'記錄器(在init_other_logger函數內部),然后通過方法調用 2 個日志調用info()。但是您正在使用相同的 logger進行操作。


所以這:


logger.info('Hello World')

other_logger.info('Goodbye World')

本質上與此相同:


logger.info('Hello World')

logger.info('Goodbye World')

現在,兩個記錄器都輸出到文件和流中,這并不奇怪了。


解決方案

所以顯而易見的事情就是init_other_logger用另一個名字稱呼你。


我會建議反對另一個答案提出的解決方案,因為當您需要一個獨立的記錄器時,這 不是應該做的事情。文檔很好地說明了您永遠不應該直接實例化記錄器,而總是通過模塊的功能getLogger。logging


正如我們在上面發現的那樣,當你調用它時,logging.getLogger(logger_name)要么使用. 因此,當您也想要一個獨特的記錄器時,這非常有效。但是請記住,此函數是冪等的,這意味著它只會在您第一次調用它時創建一個具有給定名稱的記錄器,如果您使用相同的名稱調用它,無論您調用多少次,它都會返回該記錄器。logger_name


因此,例如:


表單的第一次調用logging.getLogger('the_rock')- 創建您獨特的記錄器


表單的第二次調用logging.getLogger('the_rock')- 獲取上述記錄器


例如,如果您執行以下操作,您會發現這特別有用:


Formatters在項目中的某個位置配置一個記錄器Filters,例如在project_root/main_package/__init__.py.

想要在位于project_root/secondary_package/__init__.py.

您可以對secondary_package/__init__.py表單進行簡單的調用:logger = logging.getLogger('main_package')您將使用該記錄器及其所有的花里胡哨。


注意力!

即使此時您將使用您的init_other_logger函數創建一個唯一的記錄器,它仍然會輸出到文件和控制臺。將此行替換other_logger = init_other_logger(__name__)為other_logger = init_other_logger('the_rock')以創建唯一的記錄器并再次運行代碼。您仍然會看到輸出寫入控制臺和文件。


為什么 ?


因為它將同時使用FileHandler和StreamHandler。


為什么 ?


因為伐木機械的工作方式。您的記錄器將通過其處理程序發出其消息,然后它將一直傳播到根記錄器,在那里它將使用StreamHandler您通過basicConfig調用附加的記錄器。因此,propagate您發現的屬性實際上就是您想要的,因為您正在創建一個自定義記錄器,您只想通過其手動附加的處理程序發出消息,而不是進一步發出任何消息。在創建唯一記錄器后取消注釋logger.propagate = False,您會看到一切都按預期工作。


查看完整回答
反對 回復 2022-06-02
?
瀟湘沐

TA貢獻1816條經驗 獲得超6個贊

您的兩個處理程序都安裝在同一個記錄器上。這就是他們不分開的原因。

logger is other_logger因為logging.getLogger(__name__) is logging.getLogger(__name__)

要么直接為第二個日志創建一個記錄器logging.Logger(name)(我知道文檔說永遠不要這樣做,但如果你想要一個完全獨立的記錄器,這是如何做到的),或者在調用時為第二個日志使用不同的名稱logging.getLogger()。


查看完整回答
反對 回復 2022-06-02
  • 2 回答
  • 0 關注
  • 196 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號