配置类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')
以上这篇python3 配置logging日志类的操作就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持。
免责声明:本站资源来自互联网收集,仅供用于学习和交流,请遵循相关法律法规,本站一切资源不代表本站立场,如有侵权、后门、不妥请联系本站删除!
稳了!魔兽国服回归的3条重磅消息!官宣时间再确认!
昨天有一位朋友在大神群里分享,自己亚服账号被封号之后居然弹出了国服的封号信息对话框。
这里面让他访问的是一个国服的战网网址,com.cn和后面的zh都非常明白地表明这就是国服战网。
而他在复制这个网址并且进行登录之后,确实是网易的网址,也就是我们熟悉的停服之后国服发布的暴雪游戏产品运营到期开放退款的说明。这是一件比较奇怪的事情,因为以前都没有出现这样的情况,现在突然提示跳转到国服战网的网址,是不是说明了简体中文客户端已经开始进行更新了呢?
更新日志
- 凤飞飞《我们的主题曲》飞跃制作[正版原抓WAV+CUE]
- 刘嘉亮《亮情歌2》[WAV+CUE][1G]
- 红馆40·谭咏麟《歌者恋歌浓情30年演唱会》3CD[低速原抓WAV+CUE][1.8G]
- 刘纬武《睡眠宝宝竖琴童谣 吉卜力工作室 白噪音安抚》[320K/MP3][193.25MB]
- 【轻音乐】曼托凡尼乐团《精选辑》2CD.1998[FLAC+CUE整轨]
- 邝美云《心中有爱》1989年香港DMIJP版1MTO东芝首版[WAV+CUE]
- 群星《情叹-发烧女声DSD》天籁女声发烧碟[WAV+CUE]
- 刘纬武《睡眠宝宝竖琴童谣 吉卜力工作室 白噪音安抚》[FLAC/分轨][748.03MB]
- 理想混蛋《Origin Sessions》[320K/MP3][37.47MB]
- 公馆青少年《我其实一点都不酷》[320K/MP3][78.78MB]
- 群星《情叹-发烧男声DSD》最值得珍藏的完美男声[WAV+CUE]
- 群星《国韵飘香·贵妃醉酒HQCD黑胶王》2CD[WAV]
- 卫兰《DAUGHTER》【低速原抓WAV+CUE】
- 公馆青少年《我其实一点都不酷》[FLAC/分轨][398.22MB]
- ZWEI《迟暮的花 (Explicit)》[320K/MP3][57.16MB]