python3 配置logging日志類的操作
配置類config_file:
from configparser import ConfigParser
class config_file:
def __init__(self,conf_filePath,encoding="utf-8"):
#打開(kāi)配置文件,實(shí)例化ConfigParser類,并以默認(rèn)utf-8的編碼格式讀取文件
self.cf = ConfigParser()
self.cf.read(conf_filePath,encoding)
def get_Int_Value(self,section,option):
#獲取整數(shù)
return self.cf.getint(section,option)
def get_boolValue(self,section,option):
#獲取布爾值
return self.cf.getboolean(section,option)
def get_strValue(self,section,option):
# 獲取字符串類型的值
return self.cf.get(section,option)
def get_floatValue(self,section,option):
# 獲取浮點(diǎn)數(shù)值
return self.cf.getfloat(section,option)
def get_sections(self):
# 獲取所有的section
return self.cf.sections()
def get_options(self,section):
# 獲取所有的option
return self.cf.options(section)
日志類:
from configparser import ConfigParser
import logging
from config_file import config_file
class Log_Test(config_file):#繼承config_file
def logging(self):
logger = logging.getLogger(self.get_strValue('log','logger_name')) #從配置文件讀取logger名
logger.setLevel(self.get_strValue('log', 'logger_level')) # 設(shè)置logger收集器的收集log級(jí)別
format_logger = logging.Formatter(self.get_strValue('log','logger_format'))
if(self.get_boolValue('log','logger_out')):
handle = logging.StreamHandler() # 指定輸出到console控制臺(tái)
handle.setLevel(self.get_strValue('log', 'logger_level')) # 讀取日志等級(jí)并設(shè)定logging的級(jí)別
handle.setFormatter(format_logger) # 指定日志格式
else:
handle = logging.FileHandler(self.get_strValue('log','logger_filepath'), encoding='utf-8')
handle.setLevel(self.get_strValue('log', 'logger_level')) # 讀取日志等級(jí)并設(shè)定logging的級(jí)別
handle.setFormatter(format_logger) # 指定日志格式
logger.addHandler(handle)
return logger
日志配置文件logging.cfg:
[log] #日志收集器 logger_name=TEST #日志級(jí)別 級(jí)別需要大寫 DEBUG-->INFO-->WARNING-->ERROR-->CRITICAL/FATAL logger_level=DEBUG #日志輸出格式 注意轉(zhuǎn)義 logger_format=%%(asctime)s-%%(filename)s-%%(levelname)s-日志信息:%%(message)s #日志是否輸出到控制臺(tái) True or False logger_out=False #日志輸出指定文件地址 logger_filepath=logging_Test.log
將讀取配置文件類進(jìn)行封裝,日志類繼承配置類。
補(bǔ)充知識(shí):Python2/Python3自定義日志類教程
一、說(shuō)明
1.1 背景說(shuō)明
Python的logging功能是比較豐富的支持不同層次的日志輸出,但或是我們想在日志前輸出時(shí)間、或是我們想要將日志輸入到文件,我們還是想要自定義日志類。
之前自己也嘗試寫過(guò)但感覺(jué)文檔太亂看不懂怎么寫,今天有人拿個(gè)半成品來(lái)問(wèn)為什么代碼報(bào)錯(cuò),在其基礎(chǔ)上改造了一下。
1.2 logging級(jí)別說(shuō)明
logging日志級(jí)別及對(duì)應(yīng)值如下,默認(rèn)情況下直接運(yùn)行只有INFO及以上級(jí)別才會(huì)輸出(本質(zhì)上是大于等于20才會(huì)輸出),調(diào)試模式運(yùn)行DEBUG日志才會(huì)輸出。
可以通過(guò)自定義輸出日志級(jí)別,指定直接運(yùn)行輸出什么級(jí)別的日志;不過(guò)調(diào)試模式打印的日志應(yīng)該是不可以修改的。
|
Level |
Numeric value |
|---|---|
|
CRITICAL |
50 |
|
ERROR |
40 |
|
WARNING |
30 |
|
INFO |
20 |
|
DEBUG |
10 |
|
NOTSET |
0 |
二、實(shí)現(xiàn)代碼
2.1 Python2實(shí)現(xiàn)代碼
# -*- coding: utf-8 -*-
import os
import datetime
import logging
class LogConfig:
def __init__(self,log_type="console"):
# 指定日志輸出到控制臺(tái)時(shí)的初始化
if log_type == "console":
logging.basicConfig(level=logging.INFO,
format='%(asctime)s %(levelname)s %(message)s',
datefmt='%Y-%m-%d %H:%M:%S',
)
# 指定日志輸出到文件的初始化
elif log_type == "file":
# 創(chuàng)建存放日志的目錄
if not os.path.exists('./log'):
os.mkdir('./log')
# 操作系統(tǒng)本身不允許文件名包含:等特殊字符,所以這里也不要用,不然賦給filename時(shí)會(huì)報(bào)錯(cuò)
nowTime = datetime.datetime.now().strftime('%Y-%m-%d')
file_name = './log/%s.log' % nowTime
# python2.7也有l(wèi)ogging.basicConfig(),但只直接用logging.basicConfig(),寫中文時(shí)會(huì)報(bào)錯(cuò)
# 所以為風(fēng)格統(tǒng)一,我們這里不使用logging.basicConfig(),全通過(guò)set設(shè)置
root_logger = logging.getLogger()
root_logger.setLevel(logging.INFO)
handler = logging.FileHandler(filename=file_name, encoding='utf-8', mode='a')
formatter = logging.Formatter('%(asctime)s %(levelname)s %(message)s')
handler.setFormatter(formatter)
root_logger.addHandler(handler)
def getLogger(self):
logger = logging.getLogger()
return logger
if __name__ == "__main__":
# log_type = "console"
log_type = "file"
logger = LogConfig(log_type).getLogger()
logger.debug('print by debug')
logger.info('print by info')
logger.warning('print by warning')
2.2 Python3實(shí)現(xiàn)代碼
python3.3 之后logging.basicConfig()中提供了handlers參數(shù),我們可借助handlers參數(shù)來(lái)指定編碼。
python3.3之前的python3版本寫法得和python2一樣。另外python3.9之后logging.basicConfig()會(huì)直接提供encoding參數(shù),到時(shí)可以更方便。
import os
import datetime
import logging
class LogConfig:
def __init__(self,log_type="console"):
# 指定日志輸出到控制臺(tái)時(shí)的初始化
if log_type == "console":
logging.basicConfig(level=logging.INFO,
format='%(asctime)s %(levelname)s %(message)s',
datefmt='%Y-%m-%d %H:%M:%S',
)
# 指定日志輸出到文件的初始化
elif log_type == "file":
# 創(chuàng)建存放日志的目錄
if not os.path.exists('./log'):
os.mkdir('./log')
# 操作系統(tǒng)本身不允許文件名包含:等特殊字符,所以這里也不要用,不然賦給filename時(shí)會(huì)報(bào)錯(cuò)
nowTime = datetime.datetime.now().strftime('%Y-%m-%d')
file_name = './log/%s.log' % nowTime
file_handler = logging.FileHandler(filename=file_name,encoding='utf-8', mode='a')
# level----指定打印的日志等級(jí);默認(rèn)為WARNING;可為NOTSET、DEBUG、INFO、WARNING、ERROR、CRITICAL
# format----指定整條日志的格式;這里設(shè)置為“時(shí)間-等級(jí)-日志內(nèi)容”
# datefmt----format中時(shí)間的格式;
# filename----日志輸出到的文件;默認(rèn)打印到控制臺(tái)
# filemode----日志文件讀寫形式;默認(rèn)為“a”;配合filename使用,如果不用filename該參數(shù)也可不用
# 本來(lái)輸出到文件使用filename和filemode兩個(gè)參數(shù)就可以了,不需要handlers
# 但是logging將日志輸出到文件時(shí)中文會(huì)亂碼,而logging.basicConfig又沒(méi)有提供指定編碼的參數(shù)(python3.9之后才提供有直接的encoding參數(shù))
# 要指定編碼只能使用handlers。另外handlers還是python3.3 之后才提供的參數(shù),在此之前的版本請(qǐng)參考python2的寫法
logging.basicConfig(level=logging.INFO,
format='%(asctime)s %(levelname)s %(message)s',
datefmt='%Y-%m-%d %H:%M:%S',
# filename=file_name,
# filemode='a',
handlers=[file_handler],
)
def getLogger(self):
logger = logging.getLogger()
return logger
if __name__ == "__main__":
# log_type = "console"
log_type = "file"
logger = LogConfig(log_type).getLogger()
logger.debug('print by debug')
logger.info('print by info')
logger.warning('print by warning')
三、日志截圖

四、更科學(xué)的日志定義方式(20200310更新)
通過(guò)近段時(shí)間的使用發(fā)現(xiàn)原先的方法就自己用用沒(méi)問(wèn)題,但與別人產(chǎn)生調(diào)用及上生產(chǎn)時(shí)就會(huì)存在幾個(gè)問(wèn)題:
第一個(gè)問(wèn)題是,直接通過(guò)logging.basicConfig()進(jìn)行配置,會(huì)同時(shí)影響被調(diào)用庫(kù)的日志設(shè)置。
第二個(gè)問(wèn)題是,原現(xiàn)的文件日志形式只能輸出到一個(gè)給定的文件,不能實(shí)現(xiàn)不同的日志類型輸出到不同的日志文件。
第三個(gè)問(wèn)題是,原現(xiàn)的文件日志形式使用"w"模式則上次日志會(huì)被清除,使用"a"模式則日志又會(huì)無(wú)限增長(zhǎng)需要注意清理。
前兩個(gè)問(wèn)題通過(guò)getLogger時(shí)給定一個(gè)名稱而不是直接獲取根logger進(jìn)行處理;第三個(gè)問(wèn)題通過(guò)使用TimedRotatingFileHandler等替換FileHandler進(jìn)行處理。
更新代碼如下:
import os
import datetime
import logging
import logging.handlers
class LogConfig:
def __init__(self):
pass
def get_console_logger(self):
def _gen_file_logger_handler():
_handler = logging.StreamHandler()
formatter = logging.Formatter(
"[%(asctime)s %(msecs)03d][%(process)d][tid=%(thread)d][%(name)s][%(levelname)s] %(message)s [%(filename)s"
" %(funcName)s %(lineno)s] ", datefmt="%Y-%m-%d %H:%M:%S")
_handler.setLevel(logging.INFO)
_handler.setFormatter(formatter)
return _handler
def _gen_console_logger():
# 解決第一個(gè)問(wèn)題--logging.basicConfig()會(huì)影響被調(diào)用庫(kù)的日志--getLogger時(shí)給定一個(gè)名稱而不是直接獲取根logger
_console_logger = logging.getLogger("console_logger")
_console_logger.addHandler(handler)
return _console_logger
handler = _gen_file_logger_handler()
console_logger = _gen_console_logger()
return console_logger
def get_file_logger(self,log_file_name):
def _make_sure_log_dir_exist():
if not os.path.isdir(log_file_dir):
os.mkdir(log_file_dir)
def _gen_file_logger_handler():
# 操作系統(tǒng)本身不允許文件名包含:等特殊字符,所以這里也不要用,不然賦給filename時(shí)會(huì)報(bào)錯(cuò)
# nowTime = datetime.datetime.now().strftime('%Y-%m-%d')
file_path = f'{log_file_dir}/{log_file_name}'
formatter = logging.Formatter(
"[%(asctime)s %(msecs)03d][%(process)d][tid=%(thread)d][%(name)s][%(levelname)s] %(message)s [%(filename)s"
" %(funcName)s %(lineno)s] ", datefmt="%Y-%m-%d %H:%M:%S")
# 解決第三個(gè)問(wèn)題--日志會(huì)不斷增大需要手動(dòng)去清理--使用TimedRotatingFileHandler等替換FileHandler
# filename----日志文件
# when----更換日志文件的時(shí)間單位
# interval----更換日志文件的時(shí)間單位個(gè)數(shù);這里是7天換一個(gè)文件
# backupCount----保存的舊日志文件個(gè)數(shù);這里即只保留上一個(gè)日志文件
# encoding----日志文件編碼
_handler = logging.handlers.TimedRotatingFileHandler(filename=file_path,when='D',interval=7,backupCount=1,encoding='utf-8')
# 實(shí)際發(fā)現(xiàn)有些時(shí)候這里setLevel并不起作用
# _handler.setLevel(logging.INFO)
_handler.setFormatter(formatter)
return _handler
def _gen_file_logger():
# 解決第二個(gè)問(wèn)題--不能定義多個(gè)日志文件--getLogger時(shí)給定一個(gè)名稱而不是直接獲取根logger
_file_logger = logging.getLogger(log_file_name)
_file_logger.addHandler(handler)
return _file_logger
log_file_dir = "log"
_make_sure_log_dir_exist()
handler = _gen_file_logger_handler()
file_logger = _gen_file_logger()
# 實(shí)際發(fā)現(xiàn)有些時(shí)候handler的setLevel并不起作用,要在這里setLevel
file_logger.setLevel(logging.INFO)
return file_logger
if __name__ == "__main__":
# log_type = "console"
# logger = LogConfig().get_console_logger()
log_type = "file"
# log_file_name不同,返回的是不同的logger,這樣就可以方便地定義多個(gè)logger
log_file_name = "random_file_name.log"
logger = LogConfig().get_file_logger(log_file_name=log_file_name)
logger.debug('print by debug')
logger.info('print by info')
logger.warning('print by warning')
以上這篇python3 配置logging日志類的操作就是小編分享給大家的全部?jī)?nèi)容了,希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
Python sorted排序方法如何實(shí)現(xiàn)
這篇文章主要介紹了Python sorted排序方法如何實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-03-03
TensorFlow卷積神經(jīng)網(wǎng)絡(luò)MNIST數(shù)據(jù)集實(shí)現(xiàn)示例
這篇文章主要介紹了TensorFlow卷積神經(jīng)網(wǎng)絡(luò)MNIST數(shù)據(jù)集的實(shí)現(xiàn)示例的過(guò)程詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2021-11-11
python實(shí)現(xiàn)的登錄和操作開(kāi)心網(wǎng)腳本分享
這篇文章主要介紹了python實(shí)現(xiàn)的登錄和操作開(kāi)心網(wǎng)腳本分享,可以登錄開(kāi)心網(wǎng),登錄后發(fā)送信息等功能,需要的朋友可以參考下2014-07-07
如何利用Python和OpenCV對(duì)圖像進(jìn)行加水印詳解
Python使用opencv是因?yàn)橛X(jué)得它足夠強(qiáng)大,很多圖像處理這塊都是用的它,最近就用opencv添加個(gè)水印,這篇文章主要給大家介紹了關(guān)于如何利用Python和OpenCV對(duì)圖像進(jìn)行加水印的相關(guān)資料,需要的朋友可以參考下2021-10-10
python matplotlib折線圖樣式實(shí)現(xiàn)過(guò)程
這篇文章主要介紹了python matplotlib折線圖樣式實(shí)現(xiàn)過(guò)程,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-11-11
Python深入學(xué)習(xí)之對(duì)象的屬性
這篇文章主要介紹了Python深入學(xué)習(xí)之對(duì)象的屬性,本文從較深的層次講解對(duì)象屬性的內(nèi)部運(yùn)行方式,需要的朋友可以參考下2014-08-08
python實(shí)戰(zhàn)小游戲之考驗(yàn)記憶力
本篇文章介紹了用python編寫的曾經(jīng)風(fēng)靡的考驗(yàn)記憶力的小游戲,詳細(xì)介紹了整個(gè)思路和過(guò)程以及代碼,通讀本篇對(duì)大家的學(xué)習(xí)或工作具有一定的價(jià)值,需要的朋友可以參考下2021-09-09
python面向?qū)ο蠓▽?shí)現(xiàn)圖書(shū)管理系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了python面向?qū)ο蠓▽?shí)現(xiàn)圖書(shū)管理系統(tǒng),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-04-04

