2 回答

TA貢獻(xiàn)1851條經(jīng)驗(yàn) 獲得超4個(gè)贊
首先,讓我們先看看發(fā)生了什么,然后再著手解決問(wèn)題。
logger = logging.getLogger(__name__) :當(dāng)你這樣做時(shí),你正在獲取或創(chuàng)建一個(gè)名為'main'. 由于這是第一次調(diào)用,它將創(chuàng)建該記錄器。
other_logger = init_other_logger(__name__): 當(dāng)你這樣做時(shí),你再次獲取或創(chuàng)建一個(gè)名為 的記錄器'main'。由于這是第二次調(diào)用,它將獲取上面創(chuàng)建的記錄器。所以你并沒(méi)有真正實(shí)例化一個(gè)新的記錄器,但是你得到了對(duì)上面創(chuàng)建的同一個(gè)記錄器的引用。您可以在調(diào)用init_other_logger表格后通過(guò)打印來(lái)檢查這一點(diǎn):) print(logger is other_logger。
接下來(lái)發(fā)生的事情是將 aFileHandler和 a添加Formatter到'main'記錄器(在init_other_logger函數(shù)內(nèi)部),然后通過(guò)方法調(diào)用 2 個(gè)日志調(diào)用info()。但是您正在使用相同的 logger進(jìn)行操作。
所以這:
logger.info('Hello World')
other_logger.info('Goodbye World')
本質(zhì)上與此相同:
logger.info('Hello World')
logger.info('Goodbye World')
現(xiàn)在,兩個(gè)記錄器都輸出到文件和流中,這并不奇怪了。
解決方案
所以顯而易見(jiàn)的事情就是init_other_logger用另一個(gè)名字稱呼你。
我會(huì)建議反對(duì)另一個(gè)答案提出的解決方案,因?yàn)楫?dāng)您需要一個(gè)獨(dú)立的記錄器時(shí),這 不是應(yīng)該做的事情。文檔很好地說(shuō)明了您永遠(yuǎn)不應(yīng)該直接實(shí)例化記錄器,而總是通過(guò)模塊的功能getLogger。logging
正如我們?cè)谏厦姘l(fā)現(xiàn)的那樣,當(dāng)你調(diào)用它時(shí),logging.getLogger(logger_name)要么使用. 因此,當(dāng)您也想要一個(gè)獨(dú)特的記錄器時(shí),這非常有效。但是請(qǐng)記住,此函數(shù)是冪等的,這意味著它只會(huì)在您第一次調(diào)用它時(shí)創(chuàng)建一個(gè)具有給定名稱的記錄器,如果您使用相同的名稱調(diào)用它,無(wú)論您調(diào)用多少次,它都會(huì)返回該記錄器。logger_name
因此,例如:
表單的第一次調(diào)用logging.getLogger('the_rock')- 創(chuàng)建您獨(dú)特的記錄器
表單的第二次調(diào)用logging.getLogger('the_rock')- 獲取上述記錄器
例如,如果您執(zhí)行以下操作,您會(huì)發(fā)現(xiàn)這特別有用:
Formatters在項(xiàng)目中的某個(gè)位置配置一個(gè)記錄器Filters,例如在project_root/main_package/__init__.py.
想要在位于project_root/secondary_package/__init__.py.
您可以對(duì)secondary_package/__init__.py表單進(jìn)行簡(jiǎn)單的調(diào)用:logger = logging.getLogger('main_package')您將使用該記錄器及其所有的花里胡哨。
注意力!
即使此時(shí)您將使用您的init_other_logger函數(shù)創(chuàng)建一個(gè)唯一的記錄器,它仍然會(huì)輸出到文件和控制臺(tái)。將此行替換other_logger = init_other_logger(__name__)為other_logger = init_other_logger('the_rock')以創(chuàng)建唯一的記錄器并再次運(yùn)行代碼。您仍然會(huì)看到輸出寫(xiě)入控制臺(tái)和文件。
為什么 ?
因?yàn)樗鼘⑼瑫r(shí)使用FileHandler和StreamHandler。
為什么 ?
因?yàn)榉ツ緳C(jī)械的工作方式。您的記錄器將通過(guò)其處理程序發(fā)出其消息,然后它將一直傳播到根記錄器,在那里它將使用StreamHandler您通過(guò)basicConfig調(diào)用附加的記錄器。因此,propagate您發(fā)現(xiàn)的屬性實(shí)際上就是您想要的,因?yàn)槟趧?chuàng)建一個(gè)自定義記錄器,您只想通過(guò)其手動(dòng)附加的處理程序發(fā)出消息,而不是進(jìn)一步發(fā)出任何消息。在創(chuàng)建唯一記錄器后取消注釋logger.propagate = False,您會(huì)看到一切都按預(yù)期工作。

TA貢獻(xiàn)1816條經(jīng)驗(yàn) 獲得超6個(gè)贊
您的兩個(gè)處理程序都安裝在同一個(gè)記錄器上。這就是他們不分開(kāi)的原因。
logger is other_logger
因?yàn)?code>logging.getLogger(__name__) is logging.getLogger(__name__)
要么直接為第二個(gè)日志創(chuàng)建一個(gè)記錄器logging.Logger(name)
(我知道文檔說(shuō)永遠(yuǎn)不要這樣做,但如果你想要一個(gè)完全獨(dú)立的記錄器,這是如何做到的),或者在調(diào)用時(shí)為第二個(gè)日志使用不同的名稱logging.getLogger()
。
添加回答
舉報(bào)