簡體   English   中英

使用多個模塊進行記錄時的記錄器層次結構和根記錄器

[英]Logger hierarchy and the root logger when logging with multiple modules

我有這個設置:

main.py
/module
/module/__init__.py (empty)
/module.py

這是我的兩個文件main.pymodule.py的代碼:

主文件

import logging
from module import module

logger = logging.getLogger(__name__)

def test():
    logger.warning('in main.py/test')

def main():
    handler = logging.StreamHandler()
    handler.setLevel(logging.INFO)
    formatter = logging.Formatter('%(asctime)s %(name)s/%(module)s [%(levelname)s]: %(message)s', '%Y-%m-%d %H:%M:%S')
    handler.setFormatter(formatter)
    logger.addHandler(handler)

    logger.warning('in main.py/main')
    module.something()

if __name__ == "__main__":
    main()    

模塊.py

import logging
logger = logging.getLogger(__name__)

def something():
    logger.warning('in module.py/something')

所以,我注意到它輸出以下內容(注意模塊記錄器如何沒有格式):

2019-10-01 09:03:40 __main__/main [WARNING]: in main.py/main
in module.py/something

似乎只有在我在main.py中進行編輯以將logger = logging.getLogger( __ name __ )更改為logger = logging.getLogger()def main(): ) 之后添加logger = logging.getLogger()之后:它像這樣記錄(這是我想要的):

2019-10-01 09:04:13 root/main [WARNING]: in main.py/main
2019-10-01 09:04:13 module.module/module [WARNING]: in module.py/something

這是為什么? 我認為因為main.py正在導入module.py ,所以它在層次規模上自然更高,因此module.py將繼承main.py中定義的記錄器設置。 是否需要在 main 中顯式設置根記錄器(使用logger = logging.getLogger() )才能使 inheritance 正常工作? 我沒有正確配置我的文件夾結構以使module.py的記錄器繼承main.py的記錄器設置,還是文件夾結構無關緊要?

我問的原因是因為我認為應該始終使用logger = logging.getLogger( __ name __ ) (甚至在main.py中),然后根據導入結構(或文件夾結構?),這將確定層次結構和記錄器會相應地繼承。 我做出這個假設的原因是因為如果我將main.py導入另一個程序會怎樣? 我想我的意思是,我想讓日志記錄盡可能通用,這樣我就可以將一個模塊導入另一個模塊,並且它總是繼承父級的記錄器設置。 有沒有辦法顯示所有模塊的底層層次結構以進行調試/學習?

日志層次結構與程序中的文件結構無關。 層次結構僅由記錄器的名稱確定。 當您配置一個記錄器時,除非另有明確說明,否則名稱前綴中的所有記錄器都是其子級並繼承其配置。

在您的示例中,日志記錄設置更多地與執行順序和您選擇的名稱有關。 當您的程序運行時,它會執行以下操作:

  1. 由於import logging ,從標准庫運行logging.py
  2. 運行module.py以實現from module import module
  3. main中的logger屬性設置為名為__main__Logger
  4. 創建test function
  5. 創建main function
  6. 運行主function

這一系列事件的一些后果:

  • module.loggermain.logger之前創建。 這不會影響您看到的行為,但在這種情況下值得注意。
  • 如果您將main作為腳本調用,則main.logger被命名為__main__ 如果它被稱為main ,您看到的行為不會改變,例如從python -m main
  • module顯然與main不在同一層次結構中。 兩者都是沿不同分支的根記錄器的后代。

最后一項確實是您問題的答案。 如果您希望程序中的所有記錄器共享相同的默認記錄方法,則應配置根記錄器,或確保它們具有相同的名稱前綴,然后將其配置為就像它是根記錄器一樣。

您可以讓所有記錄器從main繼承。 module/module.py ,你會做

logger = logging.getLogger('__main__.' + __name__)

這里的問題是名稱__main__是硬編碼的。 您不能保證它將是__main__main 你可以嘗試import main in module這樣你就可以做main.__name__ + '.' + __name__ main.__name__ + '.' + __name__ ,但這不會按預期工作。 如果main作為__main__運行,導入它實際上將創建第二個模塊 object 具有完全獨立的日志記錄層次結構。

這就是根記錄器沒有名稱的原因。 它提供了您想要的可維護性和一致性。 您不必為了找出根名稱而費盡心思。

話雖如此,您仍然應該將main.py記錄到__main__main記錄器。 根記錄器只能在導入防護中設置。 這樣,如果main作為常規模塊導入,它將尊重正在運行的驅動程序的日志記錄設置。

TL;博士

通常在程序的驅動程序中設置匿名根記錄器。 不要嘗試從__main__或驅動程序模塊名稱繼承記錄器。

暫無
暫無

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

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