天天看點

python子產品 ---logging子產品

摘要by crazyhacking:

與log4cxx一樣,分為三個部分,logger, handler,formatter.

詳細内容參考:1官網http://docs.python.org/2/howto/logging.html#formatters     

一   簡單示例 

    import logging

    logger = logging.getlogger()  # 生成一個日志對象

    # logfile是一個全局變量,它就是一個檔案名,如:'crawl.log'

    logfile = 'test.log'

    # 生成一個handler。logging支援許多handler,

    # 象filehandler, sockethandler, smtphandler等,我由于要寫

    # 檔案就使用了filehandler。    

    hdlr = logging.filehandler('sendlog.txt')

    # 成一個格式器,用于規範日志的輸出格式。如果沒有這行代碼,那麼預設的

    # 格式就是:"%(message)s"。也就是寫日志時,資訊是什麼日志中就是什麼,

    # 沒有日期,沒有資訊級别等資訊。logging支援許多種替換值,詳細請看

    # formatter的文檔說明。這裡有三項:時間,資訊級别,日志資訊

    formatter = logging.formatter('%(asctime)s %(levelname)s %(message)s')

    # 将格式器設定到處理器上

    hdlr.setformatter(formatter)

    # 将處理器加到日志對象上

    logger.addhandler(hdlr)

    # 設定日志資訊輸出的級别。logging提供多種級别的日志資訊,如:notset, 

    # debug, info, warning, error, critical等。每個級别都對應一個數值。

    # 如果不執行此句,預設為30(warning)。可以執行:logging.getlevelname

    # (logger.geteffectivelevel())來檢視預設的日志級别。日志對象對于不同

    # 的級别資訊提供不同的函數進行輸出,如:info(), error(), debug()等。當

    # 寫入日志時,小于指定級别的資訊将被忽略。是以為了輸出想要的日志級别一定

    # 要設定好此參數。這裡我設為notset(值為0),也就是想輸出所有資訊

    logger.setlevel(logging.notset)

 二  使用配置檔案

實際運用中,我們可能需要将日志的配置資訊獨立出來,這時候我們就需要用到logging的另一個功能:

test.py

logging.conf配置檔案:

轉載自:http://cjh6311882.diandian.com/post/2012-09-12/40038055234

詳細說明參考 :http://docs.python.org/2/howto/logging.html#formatters   

一個例子:

使用python的logging子產品

一、從一個使用場景開始

開發一個日志系統, 既要把日志輸出到控制台, 還要寫入日志檔案

python代碼

import logging

# 建立一個logger

logger = logging.getlogger('mylogger')

logger.setlevel(logging.debug)

# 建立一個handler,用于寫入日志檔案

fh = logging.filehandler('test.log')

fh.setlevel(logging.debug)

# 再建立一個handler,用于輸出到控制台

ch = logging.streamhandler()

ch.setlevel(logging.debug)

# 定義handler的輸出格式

formatter = logging.formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')

fh.setformatter(formatter)

ch.setformatter(formatter)

# 給logger添加handler

logger.addhandler(fh)

logger.addhandler(ch)

# 記錄一條日志

logger.info('foorbar')  

複制代碼

運作後, 在控制台和日志檔案都有一條日志:

java代碼  

1.2011-08-31 19:18:29,816 - mylogger - info - foorbar  

2011-08-31 19:18:29,816 - mylogger - info - foorbar 

二、logging子產品的api

結合上面的例子,我們說下幾個最常使用的api

logging.getlogger([name])

傳回一個logger執行個體,如果沒有指定name,傳回root logger。

隻要name相同,傳回的logger執行個體都是同一個而且隻有一個,即name和logger執行個體是

一一對應的。這意味着,無需把logger執行個體在各個子產品中傳遞。隻要知道name,就能得到 

同一個logger執行個體

python子產品 ---logging子產品

logger.setlevel(lvl)

設定logger的level, level有以下幾個級别:

notset < debug < info < warning < error < critical

如果把looger的級别設定為info, 那麼小于info級别的日志都不輸出, 大于等于info級

别的日志都輸出

logger.debug("foobar")    # 不輸出 

logger.info("foobar")        # 輸出

logger.warning("foobar") # 輸出

logger.error("foobar")      # 輸出

logger.critical("foobar")    # 輸出

logger.addhandler(hdlr)

logger可以雇傭handler來幫它處理日志, handler主要有以下幾種:

streamhandler: 輸出到控制台

filehandler:   輸出到檔案

handler還可以設定自己的level以及輸出格式。

logging.basicconfig([**kwargs])

* 這個函數用來配置root logger, 為root logger建立一個streamhandler, 

   設定預設的格式。

* 這些函數: logging.debug()、logging.info()、logging.warning()、

   logging.error()、logging.critical() 如果調用的時候發現root logger沒有任何 

   handler, 會自動調用basicconfig添加一個handler

* 如果root logger已有handler, 這個函數不做任何事情

使用basicconfig來配置root logger的輸出格式和level:

logging.basicconfig(format='%(levelname)s:%(message)s', level=logging.debug)

logging.debug('this message should appear on the console')

三、關于root logger以及logger的父子關系

python子產品 ---logging子產品

前面多次提到root logger, 實際上logger執行個體之間還有父子關系, root logger就是處于

最頂層的logger, 它是所有logger的祖先。如下圖: 

root logger是預設的logger

如果不建立logger執行個體, 直接調用logging.debug()、logging.info()logging.warning()、logging.error()、logging.critical()這些函數,

那麼使用的logger就是 root logger, 它可以自動建立,也是單執行個體的。

如何得到root logger

通過logging.getlogger()或者logging.getlogger("")得到root logger執行個體。

預設的level

root logger預設的level是logging.warning

如何表示父子關系

logger的name的命名方式可以表示logger之間的父子關系. 比如:

parent_logger = logging.getlogger('foo')

child_logger = logging.getlogger('foo.bar')

什麼是effective level

logger有一個概念,叫effective level。 如果一個logger沒有顯示地設定level,那麼它就

用父親的level。如果父親也沒有顯示地設定level, 就用父親的父親的level,以此推....

最後到達root logger,一定設定過level。預設為logging.warning

child loggers得到消息後,既把消息分發給它的handler處理,也會傳遞給所有祖先logger處理, 

來看一個例子

# 設定root logger

r = logging.getlogger()

formatter = logging.formatter('%(asctime)s - %(levelname)s - %(message)s')

r.addhandler(ch)

# 建立一個logger作為父親

p = logging.getlogger('foo')

p.setlevel(logging.debug)

formatter = logging.formatter('%(asctime)s - %(message)s')

p.addhandler(ch)

# 建立一個孩子logger

c = logging.getlogger('foo.bar')

c.debug('foo')  

輸出如下:

2011-08-31 21:04:29,893 - foo

2011-08-31 21:04:29,893 - debug - foo

可見, 孩子logger沒有任何handler,是以對消息不做處理。但是它把消息轉發給了它的父

親以及root logger。最後輸出兩條日志。

轉自:http://bbs.chinaunix.net/thread-3590256-1-1.html