最近想在python flask項(xiàng)目中使用日志功能湾盒,于是想到了python自帶的日志模塊logging. 在學(xué)習(xí)這個(gè)logging模塊之前,我們先來了解四個(gè)比較重要的概念:Logger诅妹,Handler罚勾,F(xiàn)ormatter,F(xiàn)ilter.
Logger記錄器:應(yīng)用程序代碼能直接使用的接口.
Handler處理器:將Logger記錄器產(chǎn)生的的日志發(fā)送到指定的目的地.
Filter過濾器:可以有更好的粒度控制去決定輸出哪些日志.
Formatter格式化器:決定輸出的日志格式.
Logger記錄器:
要使用logging模塊來記錄日志吭狡,首先要?jiǎng)?chuàng)建一個(gè)Logger記錄器尖殃,如果沒有顯式的進(jìn)行創(chuàng)建,則默認(rèn)創(chuàng)建一個(gè)root logger划煮,并且默認(rèn)的日志級(jí)別為WARN和處理器Handler(StreamHandler送丰,即將日志信息打印輸出在標(biāo)準(zhǔn)輸出).
創(chuàng)建Logger的方法:
logger = logging.getLogger(logger_name) #這個(gè)logger_name可以自己定義
創(chuàng)建了Logger實(shí)例之后,可以用以下方法對(duì)日志級(jí)別進(jìn)行設(shè)置:
logger.setLevel(logging.ERROR) #日志級(jí)別為ERROR弛秋,大于或者等于ERROR級(jí)別的日志才會(huì)進(jìn)行輸出
為L(zhǎng)ogger實(shí)例增加一個(gè)處理器:
logger.addHandler(handler_name) #handler_name可以自定定義
為L(zhǎng)ogger實(shí)例移除一個(gè)處理器:
logger.removeHandler(handler_name)
Handler處理器:
比較常用的處理器有三種:StreamHandler蚪战、FileHandler牵现、NullHandler
StreamHandler,即將日志信息打印輸出在標(biāo)準(zhǔn)輸出
創(chuàng)建一個(gè)StreamHandler:sh = logging.StreamHandler(stream=None)
FileHandler邀桑,即將日志信息打印輸出到文件
創(chuàng)建一個(gè)FileHandler:fh = logging.FileHandler(filename,mode='a')
NullHandler瞎疼,不做任何的格式化輸出,本質(zhì)上它是一個(gè)“什么都不做”的Handler.
Formatter格式化器:
使用Formatter格式化器設(shè)置日志信息的格式壁畸,內(nèi)容贼急,它由兩部分組成,分別是fmt和datefmt
其中fmt是日志消息格式化字符串樣式捏萍,datefmt是日期字符串樣式. 如果不指定fmt太抓,將默認(rèn)使用'%(message)s',如果不指定datefmt令杈,將默認(rèn)使用ISO8601日期格式.
fmt允許使用的變量如下:
%(name)s : Logger的名字
%(levelno)s :數(shù)字標(biāo)明日志就別
%(levelname)s :日志級(jí)別(INFO走敌、WARNING、ERROR逗噩、CRITICAL)
%(pathname)s :調(diào)用日志輸出函數(shù)的模塊的所在完整路徑
%(filename)s :調(diào)用日志輸出函數(shù)的模塊的文件名
%(module)s :調(diào)用日志輸出函數(shù)的模塊名
%(funcName)s :調(diào)用日志輸出函數(shù)的函數(shù)名
%(lineo)d :調(diào)用日志輸出函數(shù)的語句所在的代碼行
%(created)f :當(dāng)前時(shí)間掉丽,用unix標(biāo)準(zhǔn)的表示時(shí)間的浮點(diǎn)數(shù)表示
%(asctime)s :當(dāng)前時(shí)間格式,可以自定義時(shí)間格式异雁,如"%Y-%m-%d %H:%M:%S"
%(message)s :用戶自定義的日志消息
說了那么多捶障,還是來實(shí)踐一把吧,代碼如下:
import logging
try:
conn = mysql.connector.connect(
user = db_user,
password = db_passwd,
host = db_host,
port = db_port,
database = access_db)
cur = conn.cursor()
cur.execute(unormal_task_sql)
unormal_task_results = cur.fetchall()
except Exception,e:
logger = getLogger()
logger.error('fail to get data from oss db: %s:%s,cluster_name:%s'%(db_host,db_port,cluster_name))
def getLogger(logger_name="app.log",log_level=logging.ERROR,log_path="log/app.log"):
#create logger
logger = logging.getLogger(logger_name)
#create file handler
fh = logging.FileHandler(log_path,mode='a')
fh.setLevel(log_level)
#create formatter
fmt = "%(asctime)s %(levelname)s %(lineno)d %(filename)s %(message)s"
datefmt = "%Y-%m-%d %H:%M:%S"
formatter = logging.Formatter(fmt,datefmt)
#add handler and formatter to logger
fh.setFormatter(formatter)
logger.addHandler(fh)
return logger
日志路徑為:log/app.log #這個(gè)log目錄需要自行創(chuàng)建纲刀,app.log會(huì)自動(dòng)生成
logger記錄器的名字為:app_log
日志級(jí)別log_level為:ERROR級(jí)別
現(xiàn)在來看看日志輸出內(nèi)容:
2018-01-26 15:04:34 ERROR 59 util.py fail to get data from oss db: xx.xx.xx.xx:3307,cluster_name:上海金橋VPC
經(jīng)過實(shí)驗(yàn)證明项炼,handler設(shè)置了日志級(jí)別,那么logger可以不設(shè)置日志級(jí)別示绊,也同樣可以記錄日志.