簡體   English   中英

如何避免從 Python 中的自定義記錄器調用根處理程序?

[英]How to avoid root handler being called from the custom logger in Python?

我有一個具有調試級別的日志記錄模塊的基本配置 - 現在我只想創建另一個具有錯誤級別的記錄器。 我怎樣才能做到這一點?

問題是除了錯誤處理程序之外還調用了根處理程序 - 這是我想要避免的事情。

import logging
fmt = '%(asctime)s:%(funcName)s:%(lineno)d:%(levelname)s:%(name)s:%(message)s'
logging.basicConfig(level=logging.DEBUG, format=fmt)

logger = logging.getLogger('Temp')
logger.setLevel(logging.ERROR)
handler = logging.StreamHandler()
handler.setLevel(logging.ERROR)
logger.addHandler(handler)

logger.error('boo')

上面的代碼打印了兩次 boo,而我只期望一次,我不知道如何處理這個煩人的問題......

In [4]: logger.error('boo')
boo
2021-04-26 18:54:24,329:<module>:1:ERROR:Temp:boo

In [5]: logger.handlers
Out[5]: [<StreamHandler stderr (ERROR)>]

關於日志記錄模塊的一些基礎知識

  • logger:接收日志字符串的人,按預定義的級別對其進行排序,然后使用他自己的處理程序(如果有)來處理日志,並且默認情況下將日志傳遞給他的上級。
  • root logger:上級中的上級,做普通 logger 所做的所有事情,但不會將收到的日志傳遞給其他任何人。
  • handler :記錄器的私人承包商,他實際上對日志做任何事情,例如。 格式化日志,將其寫入文件或stdout ,或通過 tcp/udp 發送。
  • formatter :主題, handler應用於日志的設計。
  • basicConfig :配置root記錄器的快捷方式。 當您希望他完成所有工作並且他的所有較低級別的伐木工只會將日志傳遞給他時,這很有用。
    在沒有參數的情況下, basicConfigroot記錄器的級別設置為WARNING並將 output 日志添加到stderrStreamHandler

你做了什么

  1. 您創建了一種format並使用快捷方式basicConfig來配置root記錄器。 您希望根記錄器執行所有實際的記錄操作
  2. 您創建了一個新的低等級記錄器Temp
  3. 您希望它只接受ERROR級別及以上的日志。
  4. 您創建了另一個StreamHandler 其中 output 默認為stdout
  5. 您希望它只處理ERROR級別及以上
  6. 哦,你把它分配給了Temp記錄器,這使得5.多余,因為級別設置為3.
    哦等等,以為你只是想讓root記錄器從1.開始就完成這項工作。!
  7. 您使用記錄器記錄了一個ERROR

發生了什么

您的Temp記錄器接受了ERROR級別的字符串boo 然后告訴它的處理程序處理字符串。 由於該處理程序沒有分配任何formatter ,因此它按原樣將字符串輸出到stdoutboo
之后, Temp記錄器將字符串boo傳遞給他的上級,即root記錄器。

由於日志級別為ERROR > WARNING ,因此root記錄器接受了日志。 然后root記錄器告訴其處理程序處理字符串boo 此處理程序將格式字符串應用於boo 添加時間戳,添加位置,添加通過日志的記錄器的名稱等。
最后將結果輸出到stderr2021-04-26 18:54:24,329:<module>:1:ERROR:Temp:boo

改正它

由於您的代碼完全按照您的要求執行,因此您必須盡可能詳細地告訴它。

  • 只有在你懶惰的時候才使用basicConfig 通過刪除basicConfig行,您的問題解決了。
  • 使用logger = logging.getLogger('__name__')以便記錄器具有模塊的名稱。 查看日志並確切知道它來自哪個import path
  • 決定一個記錄器是應該為它自己保留日志還是通過propagate屬性將它傳遞到鏈上。 在您的情況下, logger.propagate = False也可以解決問題。
  • 使用dictConfig文件,這樣您就不會弄亂配置代碼。
  • 在實踐中,您不應該將處理程序添加到您的記錄器,而只是讓記錄器將日志一直傳遞給root並讓根執行實際的日志記錄。 為什么?
    • 其他人將您的代碼用作模塊,可以控制日志記錄。 例如,不是 output 到 stdout 而是到 tcp/udp,output 具有不同的格式等。
    • 您可以通過propagating=False完全關閉特定記錄器的日志記錄。
    • 如果您只將它們添加到root記錄器,您就可以准確地知道代碼中的所有處理程序和格式化程序。 您可以集中控制日志記錄。

暫無
暫無

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

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