2013-04-03 128 views
9

我想知道設置的標準是從Python應用程序中執行日誌記錄的。如何在多個模塊中使用python日誌記錄

我正在使用Logging類,並且我編寫了自己的記錄器類來實例化Logging類。我的主然後實例化我的記錄器包裝類。然而,我的主要實例化其他類,我希望這些其他類也能夠通過主記錄器對象寫入他的日誌文件。

如何使該記錄器對象可以被其他類調用?這幾乎就像我們需要某種靜態記錄器對象來使其工作。

我想問題的長短:你如何在你的代碼結構中實現日誌記錄,以便從main中實例化的所有類都可以寫入同一個日誌文件?我只需要在每個指向同一文件的類中創建一個新的日誌記錄對象?

回答

6

嘗試使用logging.getLogger()來獲取你的日誌對象實例:

http://docs.python.org/3/library/logging.html#logging.getLogger

所有調用該函數在給定的名稱返回相同的記錄器實例。這意味着記錄器實例永遠不需要在應用程序的不同部分之間傳遞。

UPDATE

推薦的方法做,這是使用getLogger()函數,並對其進行配置(設置的處理程序,格式化等):

# main.py 
import logging 
import lib 


def main(): 
    logger = logging.getLogger('custom_logger') 
    logger.setLevel(logging.INFO) 
    logger.addHandler(logging.FileHandler('test.log')) 
    logger.info('logged from main module') 
    lib.log() 

if __name__ == '__main__': 
    main() 

# lib.py 
import logging 


def log(): 
    logger = logging.getLogger('custom_logger') 
    logger.info('logged from lib module') 

如果你確實是需要延長記錄器類看看logging.setLoggerClass(klass)

更新2http://docs.python.org/2/howto/logging.html#custom-levels

定義自定義:在添加自定義級別不建議

# main.py 
import logging 
import lib 


# Extend Logger class 
CUSTOM_LEVEL_NUM = 9 
logging.addLevelName(CUSTOM_LEVEL_NUM, 'CUSTOM') 
def custom(self, msg, *args, **kwargs): 
    self._log(CUSTOM_LEVEL_NUM, msg, args, **kwargs) 
logging.Logger.custom = custom 

# Do global logger instance setup 
logger = logging.getLogger('custom_logger') 
logger.setLevel(logging.INFO) 
logger.addHandler(logging.FileHandler('test.log')) 


def main(): 
    logger = logging.getLogger('custom_logger') 
    logger.custom('logged from main module') 
    lib.log() 

if __name__ == '__main__': 
    main() 

注:關於如何添加自定義日誌記錄級別不改變日誌類

例處理程序和可能使用多個記錄器可能會爲您的其他要求做到訣竅:可選輸出到stderr。

+0

對不起,在這裏稍微密集....所以然後如果我有一個主要模塊實例化我自己的日誌類(其中包含日誌記錄類),那麼通過簡單地調用我的日誌對象很容易記錄的東西。但是,如果我的主要導入其他模塊,如何調用我的Log類方法進行日誌記錄而不將日誌句柄傳遞給每個方法?你能提供一個使用多個模塊的例子嗎? – GregH

+0

我提供了一個使用多個模塊和getLogger()函數的示例。如果您真的認爲使用getLogger創建記錄器並配置自定義處理程序,格式化程序並不足以滿足您的需求,請詳細說明自定義Logger類的基本原理,但很少有必須擴展Logger(logging.getLoggerClass())類。 – gonz

+0

@GregH我的例子有道理嗎?讓我知道如果這解決了你的問題,或者你需要進一步的解釋。 – gonz

24

我不知道你的意思是什麼Logging類 - 在Python的內置日誌中沒有這樣的類。你並不真的需要包裝:這裏是如何做到的,你寫的任意類記錄的例子:

import logging 

# This class could be imported from a utility module 
class LogMixin(object): 
    @property 
    def logger(self): 
     name = '.'.join([__name__, self.__class__.__name__]) 
     return logging.getLogger(name) 


# This class is just there to show that you can use a mixin like LogMixin 
class Base(object): 
    pass 

# This could be in a module separate from B 
class A(Base, LogMixin): 
    def __init__(self): 
     # Example of logging from a method in one of your classes 
     self.logger.debug('Hello from A') 

# This could be in a module separate from A 
class B(Base, LogMixin): 
    def __init__(self): 
     # Another example of logging from a method in one of your classes 
     self.logger.debug('Hello from B') 

def main(): 
    # Do some work to exercise logging 
    a = A() 
    b = B() 
    with open('myapp.log') as f: 
     print('Log file contents:') 
     print(f.read()) 

if __name__ == '__main__': 
    # Configure only in your main program clause 
    logging.basicConfig(level=logging.DEBUG, 
         filename='myapp.log', filemode='w', 
         format='%(name)s %(levelname)s %(message)s') 
    main() 

一般來說,沒有必要在一流水平有記錄器:在Python,不像說的Java,單位程序(de)組合是模塊。但是,正如我上面所顯示的,沒有任何東西阻止你這樣做。該腳本在運行時顯示:

Log file contents: 
__main__.A DEBUG Hello from A 
__main__.B DEBUG Hello from B 

請注意,來自兩個類的代碼都記錄到相同的文件myapp.log中。即使在不同的模塊中使用A和B也是如此。

+0

這是我在Python中看到的最優雅的解決方案。感謝你的分享 :-) –

相關問題