logging模塊

不少程序都有記錄日誌的需求,而且日誌中包含的信息即有正常的程序訪問日誌,還可能有錯誤、警告等信息輸出,python的logging模塊提供了標準的日誌接口,你能夠經過它存儲各類格式的日誌,logging的日誌能夠分爲 debug()info()warning()error() and critical() 5個級別html

看一下這幾個日誌級別分別表明什麼意思python

Level When it’s used
DEBUG Detailed information, typically of interest only when diagnosing problems.
INFO Confirmation that things are working as expected.
WARNING An indication that something unexpected happened, or indicative of some problem in the near future (e.g. ‘disk space low’). The software is still working as expected.
ERROR Due to a more serious problem, the software has not been able to perform some function.
CRITICAL A serious error, indicating that the program itself may be unable to continue running.

下面咱們看一下怎麼用。網絡

最簡單用法:app

import logging函數

 

logging.debug("debug test")工具

logging.info("info test")ui

logging.warning("warning test")spa

logging.error("error test")線程

logging.critical("critical test")debug

輸出:

WARNING:root:warning test
ERROR:root:error test
CRITICAL:root:critical test

這裏爲何不輸出debug和info呢?由於這裏默認的日誌級別是warning如下的日誌級別均不打印,那咱們要怎麼才能打印debug和info信息呢?咱們需設置日誌級別爲debug,這樣就能想打印哪一個級別的日誌就打印哪一個級別的日誌了

import logging

 

logging.basicConfig(level=logging.INFO) #設置日誌級別,這裏注意INFO必須爲大寫,若是設置爲DEBUG,則能打印出全部日誌

 

logging.debug("debug test")

logging.info("info test")

logging.warning("warning test")

logging.error("error test")

 

輸出:

INFO:root:info test
WARNING:root:warning test
ERROR:root:error test

這裏注意一點logging.debug("debug test")不像print函數,能夠打印多條語句,中間用逗號隔開,logging不行,logging輸出時只能一條一條的輸出,不能用逗號隔開

如:

logging.debug("abc","cba")或則logging.debug([1,2,3],[1,3,4])等均會報錯

 

 

若是想把日誌寫到文件裏,也很簡單:

import logging

 

logging.basicConfig(filename='example.log',level=logging.INFO)   #filename爲文件

 

logging.debug("debug test")

logging.info("info test")

logging.warning("warning test")

logging.error("error test")

 

輸出到example.log文件中:

INFO:root:info test

WARNING:root:warning test

ERROR:root:error test

 

感受上面的日誌忘記加上時間了,下面就來加上:

import logging

logging.basicConfig(
filename='example.log',
level=logging.DEBUG,
format='%(asctime)s %(message)s',
datefmt='%y/%m/%d %I:%M:%S %p'
)

logging.debug("debug test")
logging.info("info test")
logging.warning("warning test")
輸出:
17/05/26 03:07:22 PM debug test
17/05/26 03:07:22 PM info test
17/05/26 03:07:22 PM warning test

是否是感受輸出仍然不是很完善,缺乏行,日誌級別等,下面咱們來繼續完善
import logging
logging.basicConfig(
filename='example.log',
level=logging.DEBUG,
format='%(asctime)s %(filename)s:%(lineno)d - %(levelname)s:%(message)s', #輸出時間,文件名,行,日誌級別,信息
datefmt='%y/%m/%d %I:%M:%S %p'
)

logging.debug("debug test")
logging.info("info test")
logging.warning("warning test")
輸出:
17/05/26 03:22:40 PM logging_mod.py:11 - DEBUG:debug test
17/05/26 03:22:40 PM logging_mod.py:12 - INFO:info test
17/05/26 03:22:40 PM logging_mod.py:13 - WARNING:warning test

是否是不清楚format裏面的參數意義,看這張表格就清楚了,能夠根據須要自行添加須要打印的格式

日誌格式

 

%(name)s

Logger的名字

%(levelno)s

數字形式的日誌級別

%(levelname)s

文本形式的日誌級別

%(pathname)s

調用日誌輸出函數的模塊的完整路徑名,可能沒有

%(filename)s

調用日誌輸出函數的模塊的文件名

%(module)s

調用日誌輸出函數的模塊名

%(funcName)s

調用日誌輸出函數的函數名

%(lineno)d

調用日誌輸出函數的語句所在的代碼行

%(created)f

當前時間,用UNIX標準的表示時間的浮 點數表示

%(relativeCreated)d

輸出日誌信息時的,自Logger建立以 來的毫秒數

%(asctime)s

字符串形式的當前時間。默認格式是 「2003-07-08 16:49:45,896」。逗號後面的是毫秒

%(thread)d

線程ID。可能沒有

%(threadName)s

線程名。可能沒有

%(process)d

進程ID。可能沒有

%(message)s

用戶輸出的消息

 

若是想同時把log打印在屏幕和文件日誌裏,就須要瞭解一點複雜的知識 了


Python 使用logging模塊記錄日誌涉及四個主要類,使用官方文檔中的歸納最爲合適:

logger提供了應用程序能夠直接使用的接口;

handler將(logger建立的)日誌記錄發送到合適的目的輸出;

filter提供了細度設備來決定輸出哪條日誌記錄;

formatter決定日誌記錄的最終輸出格式。

 

logger
每一個程序在輸出信息以前都要得到一個Logger。Logger一般對應了程序的模塊名,好比聊天工具的圖形界面模塊能夠這樣得到它的Logger:
LOG=logging.getLogger(」chat.gui」)
而核心模塊能夠這樣:
LOG=logging.getLogger(」chat.kernel」)

Logger.setLevel(lel):指定最低的日誌級別,低於lel的級別將被忽略。debug是最低的內置級別,critical爲最高
Logger.addFilter(filt)、Logger.removeFilter(filt):添加或刪除指定的filter
Logger.addHandler(hdlr)、Logger.removeHandler(hdlr):增長或刪除指定的handler
Logger.debug()、Logger.info()、Logger.warning()、Logger.error()、Logger.critical():能夠設置的日誌級別

 

handler

handler對象負責發送相關的信息到指定目的地。Python的日誌系統有多種Handler可使用。有些Handler能夠把信息輸出到控制檯,有些Logger能夠把信息輸出到文件,還有些 Handler能夠把信息發送到網絡上。若是以爲不夠用,還能夠編寫本身的Handler。能夠經過addHandler()方法添加多個多handler
Handler.setLevel(lel):指定被處理的信息級別,低於lel級別的信息將被忽略
Handler.setFormatter():給這個handler選擇一個格式
Handler.addFilter(filt)、Handler.removeFilter(filt):新增或刪除一個filter對象


每一個Logger能夠附加多個Handler。接下來咱們就來介紹一些經常使用的Handler:
1) logging.StreamHandler
使用這個Handler能夠向相似與sys.stdout或者sys.stderr的任何文件對象(file object)輸出信息。它的構造函數是:
StreamHandler([strm])
其中strm參數是一個文件對象。默認是sys.stderr


2) logging.FileHandler
和StreamHandler相似,用於向一個文件輸出日誌信息。不過FileHandler會幫你打開這個文件。它的構造函數是:
FileHandler(filename[,mode])
filename是文件名,必須指定一個文件名。
mode是文件的打開方式。參見Python內置函數open()的用法。默認是’a',即添加到文件末尾。

3) logging.handlers.RotatingFileHandler
這個Handler相似於上面的FileHandler,可是它能夠管理文件大小。當文件達到必定大小以後,它會自動將當前日誌文件更名,而後建立 一個新的同名日誌文件繼續輸出。好比日誌文件是chat.log。當chat.log達到指定的大小以後,RotatingFileHandler自動把 文件更名爲chat.log.1。不過,若是chat.log.1已經存在,會先把chat.log.1重命名爲chat.log.2。。。最後從新建立 chat.log,繼續輸出日誌信息。它的構造函數是:
RotatingFileHandler( filename[, mode[, maxBytes[, backupCount]]])
其中filename和mode兩個參數和FileHandler同樣。
maxBytes用於指定日誌文件的最大文件大小。若是maxBytes爲0,意味着日誌文件能夠無限大,這時上面描述的重命名過程就不會發生。
backupCount用於指定保留的備份文件的個數。好比,若是指定爲2,當上面描述的重命名過程發生時,原有的chat.log.2並不會被改名,而是被刪除。


4) logging.handlers.TimedRotatingFileHandler
這個Handler和RotatingFileHandler相似,不過,它沒有經過判斷文件大小來決定什麼時候從新建立日誌文件,而是間隔必定時間就 自動建立新的日誌文件。重命名的過程與RotatingFileHandler相似,不過新的文件不是附加數字,而是當前時間。它的構造函數是:
TimedRotatingFileHandler( filename [,when [,interval [,backupCount]]])
其中filename參數和backupCount參數和RotatingFileHandler具備相同的意義。
interval是時間間隔。
when參數是一個字符串。表示時間間隔的單位,不區分大小寫。它有如下取值:
S 秒
M 分
H 小時
D 天
W 每星期(interval==0時表明星期一)
midnight 天天凌晨

 

同時輸出到屏幕和文件例子:

   import logging

#create logger
logger = logging.getLogger("test-log")
logger.setLevel(logging.DEBUG)

#create console handler and set level to info
ch = logging.StreamHandler()
ch.setLevel(logging.INFO)

#create file handler and set level to error

fh = logging.FileHandler('access.log',encoding='utf-8')
fh.setLevel(logging.ERROR)

#create formatter
formatter = logging.Formatter(
'%(asctime)s %(filename)s:%(lineno)d - %(levelname)s:%(message)s',
datefmt='%y/%m/%d %I:%M:%S %p'
)

#add formatter to ch and fh
ch.setFormatter(formatter)
fh.setFormatter(formatter)
#add ch and fh to logger
logger.addHandler(ch)
logger.addHandler(fh)

# 'application' code
logger.debug('debug message')
logger.info('info message')
logger.warn('warn message')
logger.error('error message')
logger.critical('critical message')
結果:
文件輸出:
17/05/26 04:36:26 PM logging_mod.py:45 - ERROR:error message
17/05/26 04:36:26 PM logging_mod.py:46 - CRITICAL:critical message
屏幕輸出:

   17/05/26 04:36:26 PM logging_mod.py:43 - INFO:info message
   17/05/26 04:36:26 PM logging_mod.py:44 - WARNING:warn message
   17/05/26 04:36:26 PM logging_mod.py:45 - ERROR:error message
   17/05/26 04:36:26 PM logging_mod.py:46 - CRITICAL:critical message

總結:

  1. 首先先建立一個logger,而後設置日誌級別(若是這裏沒設置,默認是warning級別)
  2. 建立handler,將(logger建立的)日誌記錄發送到合適的目的輸出(我這裏設置的爲屏幕輸出和文件輸出),而後設置日誌級別,如不設置,默認爲logger的日誌級別
  3. 建立formatter,格式詳見以前的日誌格式
  4. 把日誌格式添加到handler
  5. 把handler添加到logger

 

根據大小切割:

 

import logging
from logging import handlers

logger = logging.getLogger(__name__)
fh = handlers.RotatingFileHandler(filename='text.log',maxBytes=260,encoding='utf-8',backupCount=2)

formatter = logging.Formatter(
'%(asctime)s %(filename)s:%(lineno)d - %(levelname)s:%(message)s',
datefmt='%y/%m/%d %I:%M:%S %p'
)

fh.setFormatter(formatter)
logger.addHandler(fh)

logger.warning("test1")
logger.warning("test2")
logger.warning("test3")
logger.warning("test4")
logger.warning("test5")
結果爲

text.log.1:

17/05/26 06:39:27 PM logging_mod.py:62 - WARNING:test1
17/05/26 06:39:27 PM logging_mod.py:63 - WARNING:test2
17/05/26 06:39:27 PM logging_mod.py:64 - WARNING:test3
17/05/26 06:39:27 PM logging_mod.py:65 - WARNING:test4
text.log:
17/05/26 06:39:27 PM logging_mod.py:66 - WARNING:test5

輸出:當.log達到指定的大小以後,RotatingFileHandler自動把 文件更名爲.log.1。不過,若是.log.1已經存在,會先把.log.1重命名爲t.log.2。。。以此類推(若是設置了備份文件個數n,則最多隻能生成log文件n+1,如此列設置了備份文件爲2,那最多隻能生成3個log文件,分別是.log,.log.1,.log.2,當超過log文件個數,原有的.log.2並不會被改名,而是被刪除),最後從新建立 chat.log,繼續輸出日誌信息


根據時間截斷:

import logging
from logging import handlers
import time

logger = logging.getLogger(__name__)

fh = handlers.TimedRotatingFileHandler(filename='text.log',when='S',interval=2,encoding='utf-8',backupCount=2)

formatter = logging.Formatter(
'%(asctime)s %(filename)s:%(lineno)d - %(levelname)s:%(message)s',
datefmt='%y/%m/%d %I:%M:%S %p'
)

fh.setFormatter(formatter)
logger.addHandler(fh)

logger.warning("test1")
time.sleep(2)
logger.warning("test2")
time.sleep(2)
logger.warning("test3")
time.sleep(2)
logger.warning("test4")
logger.warning("test5")
輸出:

text.log:

17/05/26 07:18:35 PM logging_mod.py:70 - WARNING:test4
17/05/26 07:18:35 PM logging_mod.py:71 - WARNING:test5
text.log.2017..33:
17/05/26 07:18:33 PM logging_mod.py:68 - WARNING:test3
text.log.2017..31:
17/05/26 07:18:31 PM logging_mod.py:66 - WARNING:test2
相關文章
相關標籤/搜索