
前言
在自動化測試實踐過程中,必不可少的就是進行日志管理,方便調試和生產問題追蹤,python提供了logging模塊來進行日志的管理。下面我們就logging模塊的學習和使用進行一個層層推進演示學習。
Python的logging模塊提供了通用的日志系統,可以方便第三方模塊或應用使用。這個模塊提供了不同的日志級別,並可以采用不同的方式進行日志記錄,比如文件,HTTP GET/POST, SMTP, socket等等,甚至可以自定實現具體的日志記錄方式。
logging模塊與java的log4j的機制是一樣的,只是具體的語言實現細節有些不同。python logging模塊提供了logger、handler、filter、formatter等基礎類。
1、logger: 提供日志接口,供應用程序調用。logger最常用的操作有兩大類:配置和發送日志消息。
2、handler:將日志記錄發送到合適的目的,比如文件、socket等等。一個logger對象可以通過addhandler方法添加0到N個handler,每個hangdler又可以定義不同的日志級別,以實現日志分級過濾。
3、filter:提供了一種優雅的方式決定一個日志記錄是否發送到handler。
4、formatter:指定日志記錄的輸出格式。formatter的構造方法需要兩個參數:消息的格式字符串和日期字符串,這兩個參數是可選的。
默認情況下,logging將日志輸出至console,日志級別為WARNING。
logging中按日志級別大小關系為CRITICAL > ERROR > WARNING > INFO >DEBUG > NOTSET,當然也可以自定義日志級別。
簡單日志
下面我們看一下一個簡單的日志示例,將日志記錄輸出到console:
#-*- coding:utf-8 -*-
import logging
if __name__ == '__main__':
logging.debug(u'這是bug級別日志記錄')
logging.info(u'這是提示信息級別日志記錄')
logging.warning(u'這是警告級別日志記錄')
在console中將輸出一下信息:
WARNING:root:這是警告級別日志記錄
為什么只輸出了一條呢?因為logging默認情況下的日志輸出級別是:WANRING
日志格式和級別控制
接下來我們看看如何控制日志的輸出格式和日志級別。代碼示例如下:
#-*- coding:utf-8 -*-
import logging
if __name__ == '__main__':
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='mylog.log',
filemode='w'
)
logging.debug(u'這是debug級別日志記錄')
logging.info(u'這是信息級別日志記錄')
logging.warning(u'這是警告級別日志記錄')
在當前目錄下mylog.log文件中的內容為:
Mon, 20 Mar 2017 16:21:28 log.py [line: 14] DEBUG 這是debug級別日志記錄
Mon, 20 Mar 2017 16:21:28 log.py [line: 15] INFO 這是信息級別日志記錄
Mon, 20 Mar 2017 16:21:28 log.py [line: 16] WARNING 這是警告級別日志記錄
logging.basicConfig函數各參數說明
filename: 指定日志輸出文件名
filemode:和file函數的意義相同,指定日志文件的打開模式,‘w或a’
format:指定日志輸出格式和內容,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: 打印日志信息
datefmt:指定時間格式,同time.strtime()
level:指定日志級別,默認為logging.WARNING
stream:指定日志的輸出流,可以指定輸出到sys.stderr, sys.stdout或文件,默認輸出到sys.stderr,當stream和filename同時指定時,stream被忽略。
日志輸入定向
下面我們來看看如何把日志同時輸出到console和文件中,代碼示例如下:
#-*- coding:utf-8 -*-
import logging
if __name__ == '__main__':
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='mylog.log',
filemode='w')
#####################################################
# 定義一個StreamHandler,將info級別的或更高級別的日志輸出到標錯錯誤
# 並將其添加到當前的日志處理對象
console = logging.StreamHandler()
console.setLevel(logging.INFO)
formatter = logging.Formatter('%(name)-12s: %(levelname)-8s %(message)s')
console.setFormatter(formatter)
logging.getLogger('').addHandler(console)
####################################################
logging.debug(u"這是debug日志記錄")
logging.info(u'這是info日志記錄')
logging.warning(u'這是warning日志記錄')
在console中輸出以下日志記錄:
root : INFO 這是info日志記錄
root : WARNING 這是warning日志記錄
在當前目錄下mylog.log文件中內容為:
Mon, 20 Mar 2017 17:32:43 log.py [line: 26] DEBUG 這是debug日志記錄
Mon, 20 Mar 2017 17:32:43 log.py [line: 27] INFO 這是info日志記錄
Mon, 20 Mar 2017 17:32:43 log.py [line: 28] WARNING 這是warning日志記錄
在本示例中實現了根據不同需要,將不同級別的日志重定向輸出至不同的目標。
日志配置
在上述所有的示例中,日志的配置都是在代碼中實現,但在實際的應用過程中,我們一般都需要動態的配置日志信息,或是滿足自定義的需要,下面我們就自定義日志配置進行示例演示:
# 定義一個配置文件,這里命名為logger.conf,為標准的INI格式的文件,內容如下
###############################################
###### 下面定義了三個logger: root,demo01,demo01
[loggers]
keys=root,demo01,demo01
[logger_root]
level=DEBUG
handlers=hand01,hand02
[logger_demo01]
handlers=hand01,hand02
qualname=demo01
propagate=0
[logger_demo02]
handlers=hand01,hand03
qualname=demo02
propagate=0
###############################################
#### 下面定義了三個handler: hand01,hand02,hand03
[handlers]
keys=hand01,hand02,hand03
[handler_hand01]
class=StreamHandler
level=INFO
formatter=form02
args=(sys.stderr,)
[handler_hand02]
class=FileHandler
level=DEBUG
formatter=form01
args=('mylog.log', 'a')
[handler_hand03]
class=handlers.RotatingFileHandler
level=INFO
formatter=form02
args=('mylog.log', 'a', 10*1024*1024, 5)
###############################################
### 下面定義了兩種formatter: form01,form02
[formatters]
keys=form01,form02
[formatter_form01]
format=%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s
datefmt=%a, %d %b %Y %H:%M:%S
[formatter_form02]
format=%(name)-12s: %(levelname)-8s %(message)s
datefmt=
使用demo01 logger代碼示例:
#-*- coding:utf-8 -*-
import logging
import logging.config
if __name__ == '__main__':
logging.config.fileConfig("logger.conf")
logger = logging.getLogger("demo01")
logger.debug(u'這是demo01 debug日志記錄')
logger.info('u'這是demo01 info日志記錄')
logger.warning(u'這是demo01 warning日志記錄')
下面是使用demo02 logger代碼示例:
#-*- coding:utf-8 -*-
import logging
import logging.config
if __name__ == '__main__':
logging.config.fileConfig("logger.conf")
logger = logging.getLogger("demo02")
logger.debug(u'這是demo02 debug日志記錄')
logger.info('u'這是demo02 info日志記錄')
logger.warning(u'這是demo02 warning日志記錄')
結束語
本文從日志的基本應用到更高級的應用方式層層推進進行演示,當然了在實際的自動化測試實踐中,還需要對logging模塊進行更高級的封裝以提高其復用性,達成高可用的目的。對於測試人員而言更需要加強編程基本功,提升測試技術能力,更加靈活的應用各種基礎技術。