Python logging 模組

來源:互聯網
上載者:User

標籤:.com   ctime   過濾   roc   查詢   log   span   常用   htm   

Python logging 模組TOC
  • 前言
  • logging模組的設計
    • logger在邏輯上的繼承結構
    • 日誌輸出可到多種i/o裝置
    • 日誌格式和內容豐富
    • 日誌分層級,也是日誌在層級維度上的分類。
    • 可根據日誌對象的層級進行過濾、指定輸出i/o。
    • logger主要負責繼承關係基本單位
    • handler負責輸出方向的基本單位
    • formater負責日誌格式
    • filter負責過濾,可安置於logger和handler,配合上繼承傳播機制,靈活過濾。
  • logging.basicConfig()
  • Logger
  • handler
  • formatter
  • filter
  • log recoder
前言

Python在日誌記錄處理上是非常靈活的,且功能完備,足以滿足所有對日誌方面的需求。
如此強大,當然是日誌系統設計非常的流弊了。
除此之外,瞭解其設計時,要梳理清楚模組中幾個重要對象之間的關係,和他們各自負責的Mission任務!

logging模組的設計

可以參考JAVA的日誌系統設計,這篇文章採用幽默詼諧的語言基調,從需求出發,闡明日誌系統是怎麼設計出來的。
我這裡按照這篇文章,簡單勾畫下重點

  • 需求
    • 日誌訊息可以輸出到多種媒介中
    • 日誌訊息內容可以做格式化
    • 程式碼是通過package,module來組織分類的,要滿足不同包,不同模組的代碼,有自己的Tlog方式,同時也要有日誌分類(日誌其實就是某個Event事件發生了的記錄),由於是某個事件發生觸發了日誌,所以這個事件的層級要通過日誌來體現,所以日誌還要分層級。
    • 按照上一條需求,日誌有了層級,那麼就要在這種日誌分類上有文章可做。比如,不同記錄層級的處理方式不同,不同記錄層級之間還有有輕重緩急的關係。根據輕重緩急可以已設定某個記錄層級以上的處理方式和以下的層級的處理方式。
    • 日誌的處理和日誌的輸出兩個地方還可以定製化過濾需求。
  • 分析需求
    • 首先,要有個類來抽象出日誌訊息,這個類至少有兩個屬性時間戳記,訊息本身。日誌訊息本來就是記錄了一個事件的發生。那就用LogRecord類來表示日誌訊息。
    • LogRecord要輸出到不同媒介中,那就抽象一個Handler類,不同的Handler處理LogRecord到不同的媒介中
    • LogRecord要格式化輸出,那麼就要有一個Formatter類,不同Formatter可以處理為不同的格式類型。
    • 要滿足不同包,模組,有自己的處理方式。從使用者最後使用的角度考慮,我要每次都建立多個Handler太麻煩了,那就還需要一個來整合這些對象的一個處理器,這是一個抽象出來的類,就叫Logger。每個包,模組都可以有自己的logger,可以用獨特的名字來標識這個Logger的唯一性。
    • 日誌訊息LogRecord是分層級的,其它處理LogRecord的也都可以根據其層級做不同處理。
    • 在logger和handler這兩個日誌路由位置進行過濾。即增加一個Filter過濾對象到logger和handler。

這樣根據需求圍繞核心幾個類的關係
Logger包含Handler,Handler包含Formatter。都處理LogRecord。Logger和Handler都可以添加Filter對LogRecord進行過濾。

logger的繼承
1.就是通過logger的名字的命名層級來尋找其parent logger。使用‘.‘來表示繼承關係。2.logger的繼承其實是繼承幾個方面    2.1. level的繼承:子logger寫日誌的時候,優先使用本身設定的level,如果沒有設定,則逐層向上級父logger查詢,直到查詢到為止。最極端的情況是,使用rootlogger的預設記錄層級——WARNING.可以使用logger.getEffectivaLeve()擷取有效等級。    2.2. handler的繼承,先將日誌對象傳遞給子logger的所有handler處理,處理完畢,如果孩子的logger的propagate屬性設定的是1(TRUE),那麼日誌record對象會被傳播給上級父logger,該父logger的handler都會進行處理,如果父logger的propagate也是1,那麼會繼續向上。如果子logger的propagate就是0,就不會傳播,極端,如果是子logger都沒有handler,且不傳播,那麼就會極端的給logging.lastResort這是一個內建的handler,不會和任何一個logger關聯,and acts like StreamHandler which the event description message to the current value of sys.stderr.這個logging.lastResort是沒有formatted的,所以我們會看到就message原始格式,輸出到標準輸出中。3. 總的來說,其實是邏輯上的繼承,只是利用層級關係,可以來使用父logger的level和handler。
logger在邏輯上的繼承結構

logger的構建是通過logger的命名建立出的。名字在整個程式中都是唯一的表示。
這樣說的設計就可以實現將你自己的日誌和使用第三方模組所產生的日誌結合在一起。不用在自己的代碼中去刻意再寫相容第三方模組產生的日誌的處理。都交給logging就可以整合處理了。
Logger 間繼承關係的表示:

  • 是通過‘.‘號來表示的。如:‘foo‘ ‘foo.bar‘ ‘foo.bar.baz‘ ‘foo‘是‘foo.bar‘的父親,‘foo.bar‘ 是‘foo.bar.baz‘ 的父親。‘foo‘的父親其實就是‘root‘logger。
  • 這種等級關係的表示方法,非常類似於包和模組之間的展示層級關係的方法。
logging.basicConfig()

該模組層級函數是設定root logger.如果root logger已經有handler的化,那麼調用函數是沒有作用的,以下是源碼:

def basicConfig(**kwargs):    _acquireLock()    try:        if len(root.handlers) == 0:            filename = kwargs.get("filename")            if filename:                mode = kwargs.get("filemode", ‘a‘)                hdlr = FileHandler(filename, mode)            else:                stream = kwargs.get("stream")                hdlr = StreamHandler(stream)            fs = kwargs.get("format", BASIC_FORMAT)            dfs = kwargs.get("datefmt", None)            fmt = Formatter(fs, dfs)            hdlr.setFormatter(fmt)            root.addHandler(hdlr)            level = kwargs.get("level")            if level is not None:                root.setLevel(level)    finally:        _releaseLock()
Logger Objects
  • Loggers are never instantiated directly,but always through the module-level function logging.getLogger(name).
  • logger對象不能直接通過Logger類執行個體,都是通過模組層級函數logging.getLogger(name)調用產生的。
  • Mutiple calls to getLogger() with the same name will always return a refernece to the same Logger object.
  • Logger的繼承關係除了可以繼承父級的一些東西如level(getEffectiveLevel())。還可以通過繼承關係將LogRecord向上傳播。
    logger經常使用的方法:
方法 用法 注釋
logger.info()
logger.debug()
logger.setLevel
logger.getEffectiveLevel()
logger.getChild(suffix) 返回一個子logger,子logger的名字會是父logger名字加上suffix
logger.addFilter(filt)
logger.removeFilter(filt)
logger.addHandler(hd)
logger.removeHandler(hd)
Handler

Handler是一個基礎類,其它不同類型的handler都是繼承於它。同樣,handler也不會直接執行個體化對象,而是使用它的子類。
常用類型Handler

Handler 所在模組 注釋
StreamHandler logging
FileHandler logging
NullHandler loggging
BaseRotatingHandler logging.handlers
RotatingFileHandler logging.handlers
TimedRotatingFileHandler logging.handlers
SocketHandler logging.handlers

等等。。。

Handler常用方法:

  • Handler.addFilter()
  • Handler.removeFilter()
  • Handler.setFormatter()
  • Handler.setLevel()
Formatter

該類對象是用於對LogRecord進行格式化處理的。
Formtter對象的初始化需要指定日誌字串格式,還可以指定時間格式,和格式化字串使用的風格。
Fomatter對象是添加到Handler對象中的。

Filter

Filter對象初始化需要指定過濾logger名,只有指定的logger名所產生的LogRecord才會通過該filter,不然會被它過濾掉。logger名過濾是指不會過濾指定logger名及其子logger。

LogRecord

日誌內容的載體。
LogRecord的執行個體都是通過Logger對象的方法執行個體的
LogRecord的主要分類就是在記錄層級上的分類,分為DEBUG,INFO,WARNING,ERROR,CRITICAL

還是貼點實踐代碼吧
import logginglogging.basicConfig(filename=‘logging_train.log‘,level=logging.DEBUG)logger1 = logging.getLogger(‘1‘)logger2 = logger1.getChild(‘2‘)  # logger2繼承於logger1:即會是1.2logger2.propagate = True  # 是否向上傳遞LogRecord對象class myfilter(logging.Filter):  # 定義自己的Filter類    def __init__(self, s):  # 過濾所有不包含指定字串的日誌        self.filter_string = s    def filter(self, red):  # logger和handler會調用這個方法判定過濾結果。        if self.filter_string in red.getMessage():            return True        else:            return Falsefilter1 = myfilter(‘world‘)handler1 = logging.FileHandler(‘logging_train1.log‘)handler2 = logging.StreamHandler()formatter1 = logging.Formatter(‘%(asctime)s %(name)s %(threadName)s %(process)s %(levelname)s %(message)s‘)handler2.setFormatter(formatter1)logger1.addHandler(handler1)logger2.addHandler(handler2)logger2.addFilter(filter1)logger2.setLevel(logging.CRITICAL)logger2.error("hello world!")logger2.critical("Python is the best all over the world!")

Python logging 模組

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.