python logging日志输出到终端控制台,并分模块保存,按天保存
【代码】python 日志模块每天重新生成一个日志文件(日志按天分割),同时日志输出到终端窗口,并分模块分目录记录不同模块日志。
·
python 日志模块定制化
- 实现效果
- 内容说明
- 全部代码内容
实现效果
内容说明
- 解决问题:在自动化测试中,涉及的不仅仅是UI测试,还有接口测试、性能测试,当每个模块中内容多了的时候,想查看日志发现记录的内容什么都有翻起来太麻烦。所以对日志进行模块化分类就有一定的必要,模块化管理提高问题定位的速度。
- 当前实现的日志功能有:
a. 解决了在django中或tkinter中日志被写入被占用的问题
b. 日志按天分割保存
c. 在终端打印日志
d. 允许按模块存放日志
全部代码内容
# _*_ coding:utf-8 _*_
import inspect
import logging
import os
from logging.handlers import TimedRotatingFileHandler
__all__ = ['log']
LOG_HANDLER = True
class BasePath:
LOG_DIR = r'D:\Log' # 存放日志的目录
class ReTimedRotatingFileHandler(TimedRotatingFileHandler):
"""重写一下日志回滚"""
def rotate(self, source, destination):
if not callable(self.rotator):
self.new_rename(destination, source)
else:
self.rotator(source, destination)
@staticmethod
def new_rename(destination, source):
"""rename 当前日志文件时,老是被占用,改为手动创建新文件,然后再把原日志文件置空"""
if os.path.exists(source):
with open(destination, "wb+") as fw:
with open(source, "rb+") as fr:
fw.write(fr.read())
with open(source, "w+") as fw:
fw.write("")
def log_init(level=logging.INFO, name=None, filename: str = 'log.log', out_console: bool = True):
"""
每日生成一个日志文件
:param level: 日志等级
:param name: 模块名称
:param filename: 日志文件名
:param out_console: 是否在终端打印日志
:return:
:Usage:
log = log_init()
log.info('日志内容')
:其他配置:
ReTimedRotatingFileHandler(log_file_path, when='MIDNIGHT', backupCount=10, encoding="UTF-8")
:when: 日志轮转的时间间隔,可选值为 ‘S’、‘M’、‘H’、‘D’、‘W’ 和 ‘midnight’,分别表示秒、分、时、天、周和每天的午夜;默认值为 ‘midnight’,即每天的午夜轮转,值不区分大小写
:backupCount: 备份文件数目;当生成的日志文件数量超过该数目时,会自动删除旧的备份日志文件;默认值为 0,表示不备份
"""
log_file_path = os.path.join(BasePath.LOG_DIR, filename)
log_dir = os.path.dirname(log_file_path)
if not os.path.exists(log_dir):
os.makedirs(log_dir, exist_ok=True)
logger = logging.getLogger(name)
logger.setLevel(level)
# 日志输出格式
fmt = '%(levelname)s %(name)s %(asctime)s %(filename)s[%(lineno)d] \t%(message)s'
formatter = logging.Formatter(fmt)
# 输出到控制台
if out_console:
sh = logging.StreamHandler()
sh.setFormatter(formatter)
global LOG_HANDLER
if LOG_HANDLER:
logger.addHandler(sh)
LOG_HANDLER = False
# 输出到文件,每日一个文件
fh = ReTimedRotatingFileHandler(log_file_path, when='MIDNIGHT', backupCount=10, encoding="UTF-8")
fh.setFormatter(formatter)
logger.addHandler(fh)
return logger
class Log:
"""
日志分模块记录
:Usage:
log = Log()
log.system.info('hello world!')
:拓展示例: 新增类属性,指定唯一模块名称,例如:system
@property
def system(self, log_name='system') -> logging:
return self.__log_construct(log_name)
template:
@property
def 模块名(self, log_name='模块名') -> logging:
return self.__log_construct(log_name)
:日志模式:
1、模式:总-分,,即:所有日志(含模块日志)都会记录在 /Log/log.log文件中,并且其他模块日志分开记录 /Log/system/log.log
初始化方法:
log = Log()
log.info('')
2、模式:分-分,即:所有日志记录在对应模块中,不进行日志汇总
初始化方法:
log = Log()
log.system.info('') system 这个可以是任意模块
"""
_LOGBOX = {}
def __init__(self):
self.class_methods = [name for name, value in inspect.getmembers(Log) if not name.startswith('_')]
@property
def system(self, log_name='system') -> logging:
return self.__log_construct(log_name)
@property
def ui(self, log_name='ui') -> logging:
return self.__log_construct(log_name)
@property
def api(self, log_name='api') -> logging:
return self.__log_construct(log_name)
def __log_construct(self, log_name: str = None) -> logging:
log_obj = self._LOGBOX.get(log_name)
if not log_obj:
log_obj = self._LOGBOX[log_name] = log_init(name=log_name,
filename=os.path.join(BasePath.LOG_DIR, f'{log_name}/log.log'))
return log_obj
def __getattr__(self, item, log_name='log'):
if item not in self.class_methods:
log_obj = self._LOGBOX.get(log_name)
if not log_obj:
log_obj = self._LOGBOX[log_name] = log_init()
return getattr(log_obj, item)
log = Log()
if __name__ == '__main__':
log.system.info('hello world')
更多推荐
已为社区贡献1条内容
所有评论(0)