python3 配置logging日志类的操作
作者:耳虫 发布时间:2021-04-22 20:15:09
配置类config_file:
from configparser import ConfigParser
class config_file:
def __init__(self,conf_filePath,encoding="utf-8"):
#打开配置文件,实例化ConfigParser类,并以默认utf-8的编码格式读取文件
self.cf = ConfigParser()
self.cf.read(conf_filePath,encoding)
def get_Int_Value(self,section,option):
#获取整数
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):
# 获取浮点数值
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')) # 设置logger收集器的收集log级别
format_logger = logging.Formatter(self.get_strValue('log','logger_format'))
if(self.get_boolValue('log','logger_out')):
handle = logging.StreamHandler() # 指定输出到console控制台
handle.setLevel(self.get_strValue('log', 'logger_level')) # 读取日志等级并设定logging的级别
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')) # 读取日志等级并设定logging的级别
handle.setFormatter(format_logger) # 指定日志格式
logger.addHandler(handle)
return logger
日志配置文件logging.cfg:
[log]
#日志收集器
logger_name=TEST
#日志级别 级别需要大写 DEBUG-->INFO-->WARNING-->ERROR-->CRITICAL/FATAL
logger_level=DEBUG
#日志输出格式 注意转义
logger_format=%%(asctime)s-%%(filename)s-%%(levelname)s-日志信息:%%(message)s
#日志是否输出到控制台 True or False
logger_out=False
#日志输出指定文件地址
logger_filepath=logging_Test.log
将读取配置文件类进行封装,日志类继承配置类。
补充知识:Python2/Python3自定义日志类教程
一、说明
1.1 背景说明
Python的logging功能是比较丰富的支持不同层次的日志输出,但或是我们想在日志前输出时间、或是我们想要将日志输入到文件,我们还是想要自定义日志类。
之前自己也尝试写过但感觉文档太乱看不懂怎么写,今天有人拿个半成品来问为什么代码报错,在其基础上改造了一下。
1.2 logging级别说明
logging日志级别及对应值如下,默认情况下直接运行只有INFO及以上级别才会输出(本质上是大于等于20才会输出),调试模式运行DEBUG日志才会输出。
可以通过自定义输出日志级别,指定直接运行输出什么级别的日志;不过调试模式打印的日志应该是不可以修改的。
Level | Numeric value |
---|---|
CRITICAL | 50 |
ERROR | 40 |
WARNING | 30 |
INFO | 20 |
DEBUG | 10 |
NOTSET | 0 |
二、实现代码
2.1 Python2实现代码
# -*- coding: utf-8 -*-
import os
import datetime
import logging
class LogConfig:
def __init__(self,log_type="console"):
# 指定日志输出到控制台时的初始化
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":
# 创建存放日志的目录
if not os.path.exists('./log'):
os.mkdir('./log')
# 操作系统本身不允许文件名包含:等特殊字符,所以这里也不要用,不然赋给filename时会报错
nowTime = datetime.datetime.now().strftime('%Y-%m-%d')
file_name = './log/%s.log' % nowTime
# python2.7也有logging.basicConfig(),但只直接用logging.basicConfig(),写中文时会报错
# 所以为风格统一,我们这里不使用logging.basicConfig(),全通过set设置
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实现代码
python3.3 之后logging.basicConfig()中提供了handlers参数,我们可借助handlers参数来指定编码。
python3.3之前的python3版本写法得和python2一样。另外python3.9之后logging.basicConfig()会直接提供encoding参数,到时可以更方便。
import os
import datetime
import logging
class LogConfig:
def __init__(self,log_type="console"):
# 指定日志输出到控制台时的初始化
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":
# 创建存放日志的目录
if not os.path.exists('./log'):
os.mkdir('./log')
# 操作系统本身不允许文件名包含:等特殊字符,所以这里也不要用,不然赋给filename时会报错
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----指定打印的日志等级;默认为WARNING;可为NOTSET、DEBUG、INFO、WARNING、ERROR、CRITICAL
# format----指定整条日志的格式;这里设置为“时间-等级-日志内容”
# datefmt----format中时间的格式;
# filename----日志输出到的文件;默认打印到控制台
# filemode----日志文件读写形式;默认为“a”;配合filename使用,如果不用filename该参数也可不用
# 本来输出到文件使用filename和filemode两个参数就可以了,不需要handlers
# 但是logging将日志输出到文件时中文会乱码,而logging.basicConfig又没有提供指定编码的参数(python3.9之后才提供有直接的encoding参数)
# 要指定编码只能使用handlers。另外handlers还是python3.3 之后才提供的参数,在此之前的版本请参考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')
三、日志截图
四、更科学的日志定义方式(20200310更新)
通过近段时间的使用发现原先的方法就自己用用没问题,但与别人产生调用及上生产时就会存在几个问题:
第一个问题是,直接通过logging.basicConfig()进行配置,会同时影响被调用库的日志设置。
第二个问题是,原现的文件日志形式只能输出到一个给定的文件,不能实现不同的日志类型输出到不同的日志文件。
第三个问题是,原现的文件日志形式使用"w"模式则上次日志会被清除,使用"a"模式则日志又会无限增长需要注意清理。
前两个问题通过getLogger时给定一个名称而不是直接获取根logger进行处理;第三个问题通过使用TimedRotatingFileHandler等替换FileHandler进行处理。
更新代码如下:
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():
# 解决第一个问题--logging.basicConfig()会影响被调用库的日志--getLogger时给定一个名称而不是直接获取根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():
# 操作系统本身不允许文件名包含:等特殊字符,所以这里也不要用,不然赋给filename时会报错
# 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")
# 解决第三个问题--日志会不断增大需要手动去清理--使用TimedRotatingFileHandler等替换FileHandler
# filename----日志文件
# when----更换日志文件的时间单位
# interval----更换日志文件的时间单位个数;这里是7天换一个文件
# backupCount----保存的旧日志文件个数;这里即只保留上一个日志文件
# encoding----日志文件编码
_handler = logging.handlers.TimedRotatingFileHandler(filename=file_path,when='D',interval=7,backupCount=1,encoding='utf-8')
# 实际发现有些时候这里setLevel并不起作用
# _handler.setLevel(logging.INFO)
_handler.setFormatter(formatter)
return _handler
def _gen_file_logger():
# 解决第二个问题--不能定义多个日志文件--getLogger时给定一个名称而不是直接获取根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()
# 实际发现有些时候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,这样就可以方便地定义多个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')
来源:https://www.cnblogs.com/bingoTest/p/10576212.html
猜你喜欢
- 一、安装go get github.com/sirupsen/logrus二、使用1、当做标准库使用logrus实现了标准库log的方法,可
- 1. 目的在 C/C++ 开发中使用了第三方库,具体说是 .a, .lib, .dll 等文件,想通过 Python 查询出这些文件中的版本
- python中的email模块可以方便的解析邮件,先上代码#-*- encoding: gb2312 -*-import osimport
- 在Python中有时会碰到需要一个一维列向量(n*1)与另一个一维列向量(n*1)的转置(1*n)相乘,得到一个n*n的矩阵的情况。但是在p
- 服务器计算数据有时需要大量的时间,使用程序发送一封邮件是一种免费便捷的通知方式,可以让我们及时收到程序中断或者程序运行完成的信息,而不用一直
- 这篇文章主要介绍了Python爬取豆瓣视频信息代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋
- python中,A object = B object 是一种赋值操作,赋的值不是一个对象在内存中的空间,而只是这个
- (1) 单人脸情况import cv2import dlibpath = "1.jpg"img = cv2.imread
- Function Moneynm(n,m) &
- 是的,这仅仅是一个PPT文档,由Anna Debenham上传至slideshare。幻灯片的标题叫做《CSS nuggets》,嗯,很好的
- 首先添加一个splice函数:splice:该方法的作用就是从数组中删除一个元素array.splice(index,count,value
- 将数据写入Excel文件中,用python实现起来非常的简单,下面一步步地教大家。一、导入excel表格文件处理函数import xlwt注
- 一、什么是 Postman(前世今生)Postman 诞生于 2013 年,一开始只是 Abhinav Asthana 着手于解决 API
- 大家好,为了进行调试和错误跟踪,人们在整个代码库中广泛使用日志,今天来看看如何在代码中定义日志,并探讨日志的权限。一、日志层级在开始之前,需
- 本文实例为大家分享了python webp图片格式转化的具体代码,供大家参考,具体内容如下1、将本地的webp图片转换为jpg2、将下载的w
- 背景今天有人问我 “为什么数据库中有人推荐使用 int 类型来保存 IP 地址?”。现在(2020年)来看这个东西已经有点过时了,一方面是磁
- Python有大量强大又贴心的特性,如果要列个最受欢迎排行榜,那么装饰器绝对会在其中。初识装饰器,会感觉到优雅且神奇,想亲手实现时却总有距离
- 本文实例讲述了Python实现小数转化为百分数的格式化输出方法。分享给大家供大家参考,具体如下:比如将 0.1234 转化为 12.34%
- URL完全匹配(具体的url)/indexURL模糊匹配(你根本就不知道index后面是什么,它根本不会返回参数)/index/\dURL带
- Python中有哪几种方法安装第三方模块,安装Python第三方模块的方法有很多,这里介绍三种方法安装第三方模块。【方法一】: 通过setu