python的logging模塊提供了通用的日誌系統,能夠方便第三方模塊或應用使用。html
import logging # logging.config.fileConfig("./logging.conf") logging.basicConfig(filename='logger.log', level=logging.INFO) # create logger logger_name1 = "example01" logger = logging.getLogger(logger_name1) logger.debug('debug message') logger.info('info message') logger.warn('warn message') logger.error('error message') logger.critical('critical message')
控制檯無打印信息,發現當前工做目錄下生成了logger.log,內容爲:python
INFO:example01:info message
WARNING:example01:warn message
ERROR:example01:error message
CRITICAL:example01:critical message
該模塊能夠配置哪些信息:網絡
Logging模塊提供Logger,handler,filter,formatter。less
級別 | 什麼時候使用 |
---|---|
DEBUG | 詳細信息,典型地調試問題時會感興趣。 |
INFO | 證實事情按預期工做。 |
WARNING | 代表發生了一些意外,或者不久的未來會發生問題(如‘磁盤滿了’)。軟件仍是在正常工做。 |
ERROR | 因爲更嚴重的問題,軟件已不能執行一些功能了。 |
CRITICAL | 嚴重錯誤,代表軟件已不能繼續運行了。 |
Logger是一個樹形層級結構,在使用接口debug,info,warn,error,critical以前必須建立Logger實例socket
建立方法:
logger = logging.getLogger(logger_name)
函數
Handler處理器類型有不少種,比較經常使用的有三個,StreamHandler,FileHandler,NullHandler,詳情能夠訪問Python logging.handlers佈局
建立StreamHandler以後,能夠經過使用如下方法設置日誌級別,設置格式化器Formatter,增長或刪除過濾器Filter。學習
建立方法: sh = logging.StreamHandler(stream=None)
建立方法:
fh = logging.FileHandler(filename, mode='a', encoding=None, delay=False)
this
使用Formatter對象設置日誌信息最後的規則、結構和內容,默認的時間格式爲%Y-%m-%d %H:%M:%S。spa
建立方法:
formatter = logging.Formatter(fmt=None, datefmt=None)
其中,fmt是消息的格式化字符串,datefmt是日期字符串。若是不指明fmt,將使用'%(message)s'。若是不指明datefmt,將使用ISO8601日期格式。
格式 | 描述 |
---|---|
%(levelno)s | 打印日誌級別的數值 |
%(levelname)s | 打印日誌級別名稱 |
%(pathname)s | 打印當前執行程序的路徑 |
%(filename)s | 打印當前執行程序名稱 |
%(funcName)s | 打印日誌的當前函數 |
%(lineno)d | 打印日誌的當前行號 |
%(asctime)s | 打印日誌的時間 |
%(thread)d | 打印線程id |
%(threadName)s | 打印線程名稱 |
%(process)d | 打印進程ID |
%(message)s | 打印日誌信息 |
Handlers和Loggers可使用Filters來完成比級別更復雜的過濾。Filter基類只容許特定Logger層次如下的事件。例如用‘A.B’初始化的Filter容許Logger ‘A.B’, ‘A.B.C’, ‘A.B.C.D’, ‘A.B.D’等記錄的事件,logger‘A.BB’, ‘B.A.B’ 等就不行。 若是用空字符串來初始化,全部的事件都接受。
建立方法:
filter = logging.Filter(name='')
%(name)s Logger的名字 %(levelname)s 文本形式的日誌級別 %(message)s 用戶輸出的消息 %(asctime)s 字符串形式的當前時間。默認格式是 「2003-07-08 16:49:45,896」。逗號後面的是毫秒 %(levelno)s 數字形式的日誌級別 %(pathname)s 調用日誌輸出函數的模塊的完整路徑名,可能沒有 %(filename)s 調用日誌輸出函數的模塊的文件名 %(module)s 調用日誌輸出函數的模塊名 %(funcName)s 調用日誌輸出函數的函數名 %(lineno)d 調用日誌輸出函數的語句所在的代碼行 %(created)f 當前時間,用UNIX標準的表示時間的浮 點數表示 %(relativeCreated)d 輸出日誌信息時來自Logger建立的毫秒數 %(thread)d 線程ID。可能沒有 %(threadName)s 線程名。可能沒有 %(process)d 進程ID。可能沒有
一、在調試窗口上只打出error以上級別的日誌,可是在日誌中打出debug以上的信息
1 import logging 2 3 logger = logging.getLogger("simple_example") 4 logger.setLevel(logging.DEBUG) 5 6 # 創建一個filehandler來把日誌記錄在文件裏,級別爲debug以上 7 fh = logging.FileHandler("spam.log") 8 fh.setLevel(logging.DEBUG) 9 10 # 創建一個streamhandler來把日誌打在CMD窗口上,級別爲error以上 11 ch = logging.StreamHandler() 12 ch.setLevel(logging.ERROR) 13 14 # 設置日誌格式 15 formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s") 16 ch.setFormatter(formatter) 17 fh.setFormatter(formatter) 18 19 # 將相應的handler添加在logger對象中 20 logger.addHandler(ch) 21 logger.addHandler(fh) 22 23 # 開始打日誌 24 logger.debug("debug message") 25 logger.info("info message") 26 logger.warn("warn message") 27 logger.error("error message") 28 logger.critical("critical message")
這樣每次使用的時候,只要實例化一個對象就能夠了
1 #! /usr/bin/python3 2 3 import logging 4 5 6 class Logger: 7 def __init__(self, path, clevel=logging.DEBUG, Flevel=logging.DEBUG): 8 self.logger = logging.getLogger(path) 9 self.logger.setLevel(logging.DEBUG) 10 fmt = logging.Formatter('[%(asctime)s] [%(levelname)s] %(message)s', '%Y-%m-%d %H:%M:%S') 11 12 # 設置CMD日誌 13 sh = logging.StreamHandler() 14 sh.setFormatter(fmt) 15 sh.setLevel(clevel) 16 17 # 設置文件日誌 18 fh = logging.FileHandler(path) 19 fh.setFormatter(fmt) 20 fh.setLevel(Flevel) 21 self.logger.addHandler(sh) 22 self.logger.addHandler(fh) 23 24 def debug(self, message): 25 self.logger.debug(message) 26 27 def info(self, message): 28 self.logger.info(message) 29 30 def war(self, message): 31 self.logger.warn(message) 32 33 def error(self, message): 34 self.logger.error(message) 35 36 def cri(self, message): 37 self.logger.critical(message) 38 39 40 if __name__ == '__main__': 41 logyyx = Logger('yyx.log', logging.ERROR, logging.DEBUG) 42 logyyx.debug('一個debug信息') 43 logyyx.info('一個info信息') 44 logyyx.war('一個warning信息') 45 logyyx.error('一個error信息') 46 logyyx.cri('一個致命critical信息')
調試運行結果:
/usr/bin/python3.5 /home/rxf/python3_1000/1000/python3_server/logging封裝/封裝爲一個類.py [2017-11-07 10:25:50] [ERROR] 一個error信息 [2017-11-07 10:25:50] [CRITICAL] 一個致命critical信息
日誌文件內的內容:
[2017-11-07 10:25:50] [DEBUG] 一個debug信息 [2017-11-07 10:25:50] [INFO] 一個info信息 [2017-11-07 10:25:50] [WARNING] 一個warning信息 [2017-11-07 10:25:50] [ERROR] 一個error信息 [2017-11-07 10:25:50] [CRITICAL] 一個致命critical信息
logging模塊保證在同一個python解釋器內,屢次調用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=
1 import logging 2 import logging.config 3 import mod 4 5 logging.config.fileConfig('logging.conf') 6 root_logger = logging.getLogger('root') 7 root_logger.debug('test root logger...') 8 9 logger = logging.getLogger('main') 10 logger.info('test main logger') 11 logger.info('start import module \'mod\'...') 12 13 14 logger.debug('let\'s test mod.testLogger()') 15 mod.testLogger() 16 17 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,控制檯輸出:
/usr/bin/python3.5 /home/rxf/python3_1000/1000/python3_server/logging封裝/main.py 2017-11-07 10:53:49,228 - root - DEBUG - test root logger... 2017-11-07 10:53:49,228 - main - INFO - test main logger 2017-11-07 10:53:49,228 - main - INFO - start import module 'mod'... 2017-11-07 10:53:49,229 - main - DEBUG - let's test mod.testLogger() 2017-11-07 10:53:49,229 - main.mod - DEBUG - this is mod.testLogger... 2017-11-07 10:53:49,229 - main.mod.submod - INFO - this is submod.tst()... 2017-11-07 10:53:49,229 - root - INFO - finish test...
再看一下tst.log,logger配置中的輸出的目的地:
2017-11-07 10:56:54,189 - main - INFO - test main logger 2017-11-07 10:56:54,189 - main - INFO - start import module 'mod'... 2017-11-07 10:56:54,189 - main - DEBUG - let's test mod.testLogger() 2017-11-07 10:56:54,189 - main.mod - DEBUG - this is mod.testLogger... 2017-11-07 10:56:54,190 - main.mod.submod - INFO - this is submod.tst()...
tst.log中沒有root logger輸出的信息,由於logging.conf中配置了只有main logger及其子logger使用RotatingFileHandler,而root logger是輸出到標準輸出。
學習思考思路參考:
參考文章:
http://www.jb51.net/article/88449.htm
http://www.jianshu.com/p/feb86c06c4f4