[英]Python logging - config file in multiple modules with root logger
[英]Logger hierarchy and the root logger when logging with multiple modules
我有這個設置:
main.py
/module
/module/__init__.py (empty)
/module.py
這是我的兩個文件main.py
和module.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
導入另一個程序會怎樣? 我想我的意思是,我想讓日志記錄盡可能通用,這樣我就可以將一個模塊導入另一個模塊,並且它總是繼承父級的記錄器設置。 有沒有辦法顯示所有模塊的底層層次結構以進行調試/學習?
日志層次結構與程序中的文件結構無關。 層次結構僅由記錄器的名稱確定。 當您配置一個記錄器時,除非另有明確說明,否則名稱前綴中的所有記錄器都是其子級並繼承其配置。
在您的示例中,日志記錄設置更多地與執行順序和您選擇的名稱有關。 當您的程序運行時,它會執行以下操作:
import logging
,從標准庫運行logging.py
module.py
以實現from module import module
main
中的logger
屬性設置為名為__main__
的Logger
。test
functionmain
function這一系列事件的一些后果:
module.logger
在main.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.