-
logging介紹
Python的logging模塊提供了通用的日志系統(tǒng)辜窑,可以方便第三方模塊或者是應(yīng)用使用。這個模塊提供不同的日志級別寨躁,并可以采用不同的方式記錄日志穆碎,比如文件,HTTP GET/POST职恳,SMTP所禀,Socket等,甚至可以自己實現(xiàn)具體的日志記錄方式放钦。logging模塊與log4j的機制是一樣的色徘,只是具體的實現(xiàn)細(xì)節(jié)不同。模塊提供logger操禀,handler褂策,filter,formatter床蜘。 logger:提供日志接口辙培,供應(yīng)用代碼使用。logger最長用的操作有兩類:配置和發(fā)送日志消息邢锯⊙锶铮可以通過logging.getLogger(name)獲取logger對象,如果不指定name則返回root對象丹擎,多次使用相同的name調(diào)用getLogger方法返回同一個logger對象尾抑。 handler:將日志記錄(log record)發(fā)送到合適的目的地(destination),比如文件蒂培,socket等再愈。一個logger對象可以通過addHandler方法添加0到多個handler,每個handler又可以定義不同日志級別护戳,以實現(xiàn)日志分級過濾顯示翎冲。 filter:提供一種優(yōu)雅的方式?jīng)Q定一個日志記錄是否發(fā)送到handler。 formatter:指定日志記錄輸出的具體格式媳荒。formatter的構(gòu)造方法需要兩個參數(shù):消息的格式字符串和日期字符串抗悍,這兩個參數(shù)都是可選的驹饺。 與log4j類似,logger缴渊,handler和日志消息的調(diào)用可以有具體的日志級別(Level)赏壹,只有在日志消息的級別大于logger和handler的級別。
import logging
import logging.handlers
LOG_FILE = 'tst.log'
handler = logging.handlers.RotatingFileHandler(LOG_FILE, maxBytes = 1024*1024, backupCount = 5) # 實例化handler
fmt = '%(asctime)s - %(filename)s:%(lineno)s - %(name)s - %(message)s'
formatter = logging.Formatter(fmt) # 實例化formatter
handler.setFormatter(formatter) # 為handler添加formatter
logger = logging.getLogger('tst') # 獲取名為tst的logger
logger.addHandler(handler) # 為logger添加handler
logger.setLevel(logging.DEBUG)
logger.info('first info message')
logger.debug('first debug message')
輸出:
2012-03-04 23:21:59,682 - log_test.py:16 - tst - first info message
2012-03-04 23:21:59,682 - log_test.py:17 - tst - first debug message
關(guān)于formatter的配置衔沼,采用的是%(<dict key>)s的形式蝌借,就是字典的關(guān)鍵字替換。提供的關(guān)鍵字包括:
Format Description
%(name)s Name of the logger (logging channel).
%(levelno)s Numeric logging level for the message (DEBUG, INFO, WARNING, ERROR, CRITICAL).
%(levelname)s Text logging level for the message ('DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL').
%(pathname)s Full pathname of the source file where the logging call was issued (if available).
%(filename)s Filename portion of pathname.
%(module)s Module (name portion of filename).
%(funcName)s Name of function containing the logging call.
%(lineno)d Source line number where the logging call was issued (if available).
%(created)f Time when the LogRecord was created (as returned by time.time()).
%(relativeCreated)d Time in milliseconds when the LogRecord was created, relative to the time the logging module was loaded.
%(asctime)s Human-readable time when the LogRecord was created. By default this is of the form “2003-07-08 16:49:45,896” (the numbers after the comma are millisecond portion of the time).
%(msecs)d Millisecond portion of the time when the LogRecord was created.
%(thread)d Thread ID (if available).
%(threadName)s Thread name (if available).
%(process)d Process ID (if available).
%(message)s The logged message, computed as msg % args.
這個是摘自官網(wǎng)指蚁,提供了很多信息菩佑。
- logging的配置
logging的配置可以采用python代碼或是配置文件。python代碼的方式就是在應(yīng)用的主模塊中凝化,構(gòu)建handler擎鸠,handler,formatter等對象缘圈。而配置文件的方式是將這些對象的依賴關(guān)系分離出來放在文件中劣光。比如前面的例子就類似于python代碼的配置方式。這里看一下采用配置文件的方式糟把。
import logging
import logging.config
logging.config.fileConfig("logging.conf") # 采用配置文件
create logger
logger = logging.getLogger("simpleExample")
"application" code
logger.debug("debug message")
logger.info("info message")
logger.warn("warn message")
logger.error("error message")
logger.critical("critical message")
loggin.conf采用了模式匹配的方式進(jìn)行配置绢涡,正則表達(dá)式是r'^[(.*)]$',從而匹配出所有的組件遣疯。對于同一個組件具有多個實例的情況使用逗號‘雄可,’進(jìn)行分隔。對于一個實例的配置采用componentName_instanceName配置塊缠犀。使用這種方式還是蠻簡單的数苫。
[loggers]
keys=root,simpleExample
[handlers]
keys=consoleHandler
[formatters]
keys=simpleFormatter
[logger_root]
level=DEBUG
handlers=consoleHandler
[logger_simpleExample]
level=DEBUG
handlers=consoleHandler
qualname=simpleExample
propagate=0
[handler_consoleHandler]
class=StreamHandler
level=DEBUG
formatter=simpleFormatter
args=(sys.stdout,)
[formatter_simpleFormatter]
format=%(asctime)s - %(name)s - %(levelname)s - %(message)s
datefmt=
在指定handler的配置時,class是具體的handler類的類名辨液,可以是相對logging模塊或是全路徑類名虐急,比如需要RotatingFileHandler,則class的值可以為:RotatingFileHandler或者logging.handlers.RotatingFileHandler滔迈。args就是要傳給這個類的構(gòu)造方法的參數(shù)止吁,就是一個元組,按照構(gòu)造方法聲明的參數(shù)的順序燎悍。
輸出:
2012-03-06 00:09:35,713 - simpleExample - DEBUG - debug message
2012-03-06 00:09:35,713 - simpleExample - INFO - info message
2012-03-06 00:09:35,714 - simpleExample - WARNING - warn message
2012-03-06 00:09:35,714 - simpleExample - ERROR - error message
2012-03-06 00:09:35,714 - simpleExample - CRITICAL - critical message
這里還要明確一點敬惦,logger對象是有繼承關(guān)系的,比如名為a.b和a.c的logger都是名為a的子logger谈山,并且所有的logger對象都繼承于root俄删。如果子對象沒有添加handler等一些配置,會從父對象那繼承。這樣就可以通過這種繼承關(guān)系來復(fù)用配置畴椰。
- 多模塊使用logging
logging模塊保證在同一個python解釋器內(nèi)举哟,多次調(diào)用logging.getLogger('log_name')都會返回同一個logger實例,即使是在多個模塊的情況下迅矛。所以典型的多模塊場景下使用logging的方式是在main模塊中配置logging,這個配置會作用于多個的子模塊潜叛,然后在其他模塊中直接通過getLogger獲取Logger對象即可秽褒。
這里使用上面配置文件:
[loggers]
keys=root,main
[handlers]
keys=consoleHandler,fileHandler
[formatters]
keys=fmt
[logger_root]
level=DEBUG
handlers=consoleHandler
[logger_main]
level=DEBUG
qualname=main
handlers=fileHandler
[handler_consoleHandler]
class=StreamHandler
level=DEBUG
formatter=fmt
args=(sys.stdout,)
[handler_fileHandler]
class=logging.handlers.RotatingFileHandler
level=DEBUG
formatter=fmt
args=('tst.log','a',20000,5,)
[formatter_fmt]
format=%(asctime)s - %(name)s - %(levelname)s - %(message)s
datefmt=
主模塊main.py:
import logging
import logging.config
logging.config.fileConfig('logging.conf')
root_logger = logging.getLogger('root')
root_logger.debug('test root logger...')
logger = logging.getLogger('main')
logger.info('test main logger')
logger.info('start import module 'mod'...')
import mod
logger.debug('let's test mod.testLogger()')
mod.testLogger()
root_logger.info('finish test...')
子模塊mod.py:
import logging
import submod
logger = logging.getLogger('main.mod')
logger.info('logger of mod say something...')
def testLogger():
logger.debug('this is mod.testLogger...')
submod.tst()
子子模塊submod.py:
import logging
logger = logging.getLogger('main.mod.submod')
logger.info('logger of submod say something...')
def tst():
logger.info('this is submod.tst()...')
然后運行python main.py,控制臺輸出:
2012-03-09 18:22:22,793 - root - DEBUG - test root logger...
2012-03-09 18:22:22,793 - main - INFO - test main logger
2012-03-09 18:22:22,809 - main - INFO - start import module 'mod'...
2012-03-09 18:22:22,809 - main.mod.submod - INFO - logger of submod say something...
2012-03-09 18:22:22,809 - main.mod - INFO - logger say something...
2012-03-09 18:22:22,809 - main - DEBUG - let's test mod.testLogger()
2012-03-09 18:22:22,825 - main.mod - DEBUG - this is mod.testLogger...
2012-03-09 18:22:22,825 - main.mod.submod - INFO - this is submod.tst()...
2012-03-09 18:22:22,841 - root - INFO - finish test...
可以看出威兜,和預(yù)想的一樣销斟,然后在看一下tst.log,logger配置中的輸出的目的地:
2012-03-09 18:22:22,793 - main - INFO - test main logger
2012-03-09 18:22:22,809 - main - INFO - start import module 'mod'...
2012-03-09 18:22:22,809 - main.mod.submod - INFO - logger of submod say something...
2012-03-09 18:22:22,809 - main.mod - INFO - logger say something...
2012-03-09 18:22:22,809 - main - DEBUG - let's test mod.testLogger()
2012-03-09 18:22:22,825 - main.mod - DEBUG - this is mod.testLogger...
2012-03-09 18:22:22,825 - main.mod.submod - INFO - this is submod.tst()...
tst.log中沒有root logger輸出的信息椒舵,因為logging.conf中配置了只有main logger及其子logger使用RotatingFileHandler蚂踊,而root logger是輸出到標(biāo)準(zhǔn)輸出。