1. 程式人生 > >python logging 日誌使用

python logging 日誌使用

pyc fin fig 日期格式 五步 nbsp 條件 ldr thread

https://docs.python.org/3/library/logging.html
1、日誌級別

日誌一共分成5個等級,從低到高分別是:DEBUG INFO WARNING ERROR CRITICAL。

DEBUG:詳細的信息,通常只出現在診斷問題上
INFO:確認一切按預期運行
WARNING:一個跡象表明,一些意想不到的事情發生了,或表明一些問題在不久的將來(例如。磁盤空間低”)。這個軟件還能按預期工作。
ERROR:更嚴重的問題,軟件沒能執行一些功能
CRITICAL:一個嚴重的錯誤,這表明程序本身可能無法繼續運行

這5個等級,也分別對應5種打日誌的方法: debug 、info 、warning 、error 、critical。默認的是WARNING,當在WARNING或之上時才被跟蹤。

2、日誌輸出
有兩種方式記錄跟蹤,一種輸出控制臺,另一種是記錄到文件中,如日誌文件。

2.1、將日誌輸出到控制臺

比如,編寫一個叫做log.py的文件,如下:

# coding=utf-8  
__author__ = ‘liu.chunming‘  
import logging  
  
logging.basicConfig(level=logging.WARNING,  
                    format=‘%(asctime)s - %(filename)s[line:%(lineno)d] - %(levelname)s: %(message)s‘)  
# use logging  
logging.info(‘this is a loggging info message‘)  
logging.debug(‘this is a loggging debug message‘)  
logging.warning(‘this is loggging a warning message‘)  
logging.error(‘this is an loggging error message‘)  
logging.critical(‘this is a loggging critical message‘)  

執行上面的代碼將在Console中輸出下面信息:

2015-05-21 17:25:22,572 - log.py[line:10] - WARNING: this is loggging a warning message
2015-05-21 17:25:22,572 - log.py[line:11] - ERROR: this is an loggging error message
2015-05-21 17:25:22,572 - log.py[line:12] - CRITICAL: this is a loggging critical message

【解析】

通過logging.basicConfig函數對日誌的輸出格式及方式做相關配置,上面代碼設置日誌的輸出等級是WARNING級別,意思是WARNING級別以上的日誌才會輸出。另外還制定了日誌輸出的格式。

2.2、將日誌輸出到文件

我們還可以將日誌輸出到文件,只需要在logging.basicConfig函數中設置好輸出文件的文件名和寫文件的模式。

# coding=utf-8  
__author__ = ‘liu.chunming‘  
import logging  
  
logging.basicConfig(level=logging.WARNING,  
                    filename=‘./log/log.txt‘,  
                    filemode=‘w‘,  
                    format=‘%(asctime)s - %(filename)s[line:%(lineno)d] - %(levelname)s: %(message)s‘)  
# use logging  
logging.info(‘this is a loggging info message‘)  
logging.debug(‘this is a loggging debug message‘)  
logging.warning(‘this is loggging a warning message‘)  
logging.error(‘this is an loggging error message‘)  
logging.critical(‘this is a loggging critical message‘)  

運行之後,打開該文件./log/log.txt,效果如下:

2015-05-21 17:30:20,282 - log.py[line:12] - WARNING: this is loggging a warning message
2015-05-21 17:30:20,282 - log.py[line:13] - ERROR: this is an loggging error message
2015-05-21 17:30:20,282 - log.py[line:14] - CRITICAL: this is a loggging critical message

2.3、既要把日誌輸出到控制臺, 還要寫入日誌文件

這就需要一個叫作Logger 的對象來幫忙,下面將對他進行詳細介紹,現在這裏先學習怎麽實現把日誌既要輸出到控制臺又要輸出到文件的功能。

# coding=utf-8  
__author__ = liu.chunming  
import logging  
  
# 第一步,創建一個logger  
logger = logging.getLogger()  
logger.setLevel(logging.INFO)    # Log等級總開關  
  
# 第二步,創建一個handler,用於寫入日誌文件  
logfile = ./log/logger.txt  
fh = logging.FileHandler(logfile, mode=w)  
fh.setLevel(logging.DEBUG)   # 輸出到file的log等級的開關  
  
# 第三步,再創建一個handler,用於輸出到控制臺  
ch = logging.StreamHandler()  
ch.setLevel(logging.WARNING)   # 輸出到console的log等級的開關  
  
# 第四步,定義handler的輸出格式  
formatter = logging.Formatter("%(asctime)s - %(filename)s[line:%(lineno)d] - %(levelname)s: %(message)s")  
fh.setFormatter(formatter)  
ch.setFormatter(formatter)  
  
# 第五步,將logger添加到handler裏面  
logger.addHandler(fh)  
logger.addHandler(ch)  
  
# 日誌  
logger.debug(this is a logger debug message)  
logger.info(this is a logger info message)  
logger.warning(this is a logger warning message)  
logger.error(this is a logger error message)  
logger.critical(this is a logger critical message)  

執行這段代碼之後,在console中,可以看到:

C:\Python27\python.exe C:/Users/liu.chunming/PycharmProjects/Myproject/log.py
2015-05-21 17:47:50,292 - log.py[line:30] - WARNING: this is a logger warning message
2015-05-21 17:47:50,292 - log.py[line:31] - ERROR: this is a logger error message
2015-05-21 17:47:50,293 - log.py[line:32] - CRITICAL: this is a logger critical message
在logger.txt中,可以看到:

2015-05-21 17:47:50,292 - log.py[line:29] - INFO: this is a logger info message
2015-05-21 17:47:50,292 - log.py[line:30] - WARNING: this is a logger warning message
2015-05-21 17:47:50,292 - log.py[line:31] - ERROR: this is a logger error message
2015-05-21 17:47:50,293 - log.py[line:32] - CRITICAL: this is a logger critical message

【解析】

可以發現,實現這個功能一共分5步:

第一步,創建一個logger;第二步,創建一個handler,用於寫入日誌文件;第三步,再創建一個handler,用於輸出到控制臺;第四步,定義handler的輸出格式;第五步,將logger添加到handler裏面。這段代碼裏面提到了好多概念,包括:Logger,Handler,Formatter。後面講對這些概念進行講解。

3、日誌格式說明

logging.basicConfig函數中,可以指定日誌的輸出格式format,這個參數可以輸出很多有用的信息,如上例所示:

%(levelno)s: 打印日誌級別的數值
%(levelname)s: 打印日誌級別名稱
%(pathname)s: 打印當前執行程序的路徑,其實就是sys.argv[0]
%(filename)s: 打印當前執行程序名
%(funcName)s: 打印日誌的當前函數
%(lineno)d: 打印日誌的當前行號
%(asctime)s: 打印日誌的時間
%(thread)d: 打印線程ID
%(threadName)s: 打印線程名稱
%(process)d: 打印進程ID
%(message)s: 打印日誌信息

我在工作中給的常用格式在前面已經看到了。就是:

format=‘%(asctime)s - %(filename)s[line:%(lineno)d] - %(levelname)s: %(message)s‘

這個格式可以輸出日誌的打印時間,是哪個模塊輸出的,輸出的日誌級別是什麽,以及輸入的日誌內容。

4、高級進階

接下來學習一些日誌組件以及一些高級部分。日誌組件包括:loggers、handlers,filters,formatters.

Logger 對象扮演了三重角色.首先,它暴露給應用幾個方法以便應用可以在運行時寫log.其次,Logger對象按照log信息的嚴重程度或者根據filter對 象來決定如何處理log信息(默認的過濾功能).最後,logger還負責把log信息傳送給相關的loghandlers.

Handler對象負責分配合適的log信息(基於log信息的嚴重 程度)到handler指定的目的地.Logger對象可以用addHandler()方法添加零個或多個handler對象到它自身.一個常見的場景 是,一個應用可能希望把所有的log信息都發送到一個log文件中去,所有的error級別以上的log信息都發送到stdout,所有critical 的log信息通過email發送.這個場景裏要求三個不同handler處理,每個handler負責把特定的log信息發送到特定的地方.

filter:細致化,選擇哪些日誌輸出

format:設置顯示格式

1、logging.basicConfig([**kwargs]):

Does basic configuration for the logging system by creating a StreamHandler with a defaultFormatter and adding it to the root logger. The functionsdebug(),info(),warning(),error() andcritical() will callbasicConfig() automatically if no handlers are defined for the root logger.

This function does nothing if the root logger already has handlers configured for it.

為日誌模塊配置基本信息。kwargs 支持如下幾個關鍵字參數:
filename :日誌文件的保存路徑。如果配置了些參數,將自動創建一個FileHandler作為Handler;
filemode
:日誌文件的打開模式。 默認值為‘a‘,表示日誌消息以追加的形式添加到日誌文件中。如果設為‘w‘, 那麽每次程序啟動的時候都會創建一個新的日誌文件;
format :設置日誌輸出格式;
datefmt :定義日期格式;
level :設置日誌的級別.對低於該級別的日誌消息將被忽略;
stream :設置特定的流用於初始化StreamHandler;

演示如下:

import logging
import os
FILE=os.getcwd()

logging.basicConfig(level=logging.DEBUG,
                    format=%(asctime)s:%(filename)s[line:%(lineno)d] %(levelname)s %(message)s,
                    datefmt=%a, %d %b %Y %H:%M:%S,
                    filename = os.path.join(FILE,log.txt),
                    filemode=w)
logging.info(msg)
logging.debug(msg2)

2、logging.getLogger([name])

創建Logger對象。日誌記錄的工作主要由Logger對象來完成。在調用getLogger時要提供Logger的名稱(註:多次使用相同名稱 來調用getLogger,返回的是同一個對象的引用。),Logger實例之間有層次關系,這些關系通過Logger名稱來體現,如:

p = logging.getLogger("root")

c1 = logging.getLogger("root.c1")

c2 = logging.getLogger("root.c2")

例子中,p是父logger, c1,c2分別是p的子logger。c1, c2將繼承p的設置。如果省略了name參數, getLogger將返回日誌對象層次關系中的根Logger。

import logging
‘‘‘命名‘‘‘
log2=logging.getLogger(BeginMan)  #生成一個日誌對象
print log2  #<logging.Logger object at 0x00000000026D1710>

‘‘‘無名‘‘‘
log3 = logging.getLogger()
print log3  #<logging.RootLogger object at 0x0000000002721630> 如果沒有指定name,則返回RootLogger

‘‘‘最好的方式‘‘‘
log = logging.getLogger(__name__)#__name__ is the module’s name in the Python package namespace.
print log   #<logging.Logger object at 0x0000000001CD5518>  Logger對象
print __name__  #__main__

三、Logger對象

通過logging.getLogger(nam)來獲取Logger對象,

Class logging.Logger

有如下屬性和方法:

1、Logger.propagate

print log.propagate         #1

具體參考:http://docs.python.org/2.7/library/logging.html

2、Logger.setLevel(lvl)

設置日誌的級別。對於低於該級別的日誌消息將被忽略.

import logging
import os
logging.basicConfig(format="%(levelname)s,%(message)s",filename=os.path.join(os.getcwd(),log.txt),level=logging.DEBUG)
log = logging.getLogger(root.set)   #Logger對象
print log.propagate         #1
log.setLevel(logging.WARN)  #日誌記錄級別為WARNNING  
log.info(msg)             #不會被記錄
log.debug(msg)            #不會被記錄
log.warning(msg)
log.error(msg)

3、Logger.debug(msg [ ,*args [, **kwargs]])

記錄DEBUG級別的日誌信息。參數msg是信息的格式,args與kwargs分別是格式參數。

import logging
logging.basicConfig(filename = os.path.join(os.getcwd(), log.txt), level = logging.DEBUG)
log = logging.getLogger(root)
log.debug(%s, %s, %s, *(error, debug, info))
log.debug(%(module)s, %(info)s, {module: log, info: error})

4、同上

Logger.info(msg[ , *args[ , **kwargs] ] )

Logger.warnning(msg[ , *args[ , **kwargs] ] )

Logger.error(msg[ , *args[ , **kwargs] ] )

Logger.critical(msg[ , *args[ , **kwargs] ] )

5、Logger.log(lvl, msg[ , *args[ , **kwargs]] )

記錄日誌,參數lvl用戶設置日誌信息的級別。參數msg, *args, **kwargs的含義與Logger.debug一樣。

log.log(logging.ERROR,‘%(module)s %(info)s‘,{‘module‘:‘log日誌‘,‘info‘:‘error‘}) #ERROR,log日誌 error
log.log(logging.ERROR,‘再來一遍:%s,%s‘,*(‘log日誌‘,‘error‘))  #ERROR,再來一遍:log日誌,error

6、Logger.exception(msg[, *args])

以ERROR級別記錄日誌消息,異常跟蹤信息將被自動添加到日誌消息裏。Logger.exception通過用在異常處理塊中,如:

技術分享
import logging
import os
logging.basicConfig(format="%(levelname)s,%(message)s",filename=os.path.join(os.getcwd(),‘log.txt‘),level=logging.DEBUG)
log = logging.getLogger(‘root‘)   #Logger對象
try:
    raise Exception,u‘錯誤異常‘
except:
    log.exception(‘exception‘)  #異常信息被自動添加到日誌消息中  
打開文件,顯示如下:

‘‘‘ERROR,exception
Traceback (most recent call last):
  File "E:\project\py\src\log3.py", line 12, in <module>
    raise Exception,u‘錯誤異常‘
Exception: 錯誤異常
‘‘‘
技術分享

7、Logger.addFilter(filt)

指定過濾器

8、Logger.removeFilter(filt)

移除指定的過濾器

9、Logger.filter(record)

....其他的後面介紹

四、 Handler對象、Formatter對象、Filter對象、Filter對象

這裏簡要介紹

技術分享
#coding=utf8
‘‘‘
Created on 2013年9月23日
Function : Handler對象、Formatter對象、Filter對象、Filter對象
@author : BeginMan
‘‘‘
import logging
import os
‘‘‘Logger‘‘‘
l = logging.Logger(‘root‘)          #創建Logger對象
log = logging.getLogger(‘root‘)     #通過logging.getLogger創建Logger對象
print l                             #<logging.Logger object at 0x0000000001DF5B70>
print log                           #<logging.Logger object at 0x00000000022A16D8>

‘‘‘Handler‘‘‘
handler = logging.Handler()         #創建Handler對象
handler.__init__(logging.DEBUG)     #通過設置level來初始化Handler實例
handler.createLock()                #初始化一個線程鎖可以用來序列化訪問底層I / O功能,這可能不是線程安全的。
handler.acquire()                   #獲取線程鎖通過handler.createLock()
handler.release()                   #釋放線程鎖通過獲取handler.acquire()
handler.setLevel(logging.DEBUG)     #設置臨界值,如果Logging信息級別小於它則被忽視,當一個handler對象被創建,級別沒有被設置,導致所有的信息會被處理。
handler.setFormatter("%(levelname)s,%(message)s")              #設置格式
# handler.addFilter(filter)         #添加指定的過濾器
# handler.removeFilter(filter)      #移除指定的過濾器
# handler.filter(record)            #通過設置過濾器適用於記錄並返回真值如果要處理的記錄
handler.flush()                     #確保所有的日誌輸出已經被刷新
handler.close()                     #收拾任何所使用資源處理程序,
# handler.handle(record)            #有條件地發出指定的日誌記錄,這取決於過濾器可能被添加到處理程序。
# handler.handlerError(record)      #處理錯誤
# handler.format(record)            #格式輸出
# handler.emit(record)

#Formatter:http://docs.python.org/2.7/library/logging.html#logging.Formatter

‘‘‘Formatter:
the base Formatter allows a formatter string to be specified,is none ,used default value ‘%(message)s‘
class logging.Formatter(fmt=None,datefmt=None)
If no fmt is specified, ‘%(message)s‘ is used. If no datefmt is specified, the ISO8601 date format is used.
‘‘‘
fm = logging.Formatter(‘%(levelname)s:%(message)s‘,‘%m/%d/%Y %I:%M:%S %p‘)
print fm        #<logging.Formatter object at 0x0000000002311828>
#有如下方法:format()、formatTime()、formatException()

#http://docs.python.org/2.7/library/logging.html#formatter-objects

‘‘‘Filter‘‘‘
‘‘‘
class logging.Filter(name=‘‘):
    返回Filter實例,If name is specified, it names a logger which, together with its children, 
  will have its events allowed through the filter. If name is the empty string, allows every event.
用於Loggers、Handlers等過濾的設置
如果一個過濾器初始化為‘A.B‘,則允許‘A.B/A.B.C/A.B.C.D/A.B.D‘等,但不允許‘A.BB/B.A‘等通過
如果初始化為空字符串,則沒有過濾。
它有filter()方法
‘‘‘

‘‘‘LogRecord ‘‘‘
‘‘‘class logging.LogRecord(name, level, pathname, lineno, msg, args, exc_info, func=None)
LogRecord 實例可以被Logger自動創建.也可以通過makeLogRecord()來創建‘‘‘
#http://docs.python.org/2.7/library/logging.html#logrecord-objects

python logging 日誌使用