700字范文,内容丰富有趣,生活中的好帮手!
700字范文 > Python中如何使用logging模块记录日志

Python中如何使用logging模块记录日志

时间:2018-12-21 03:18:13

相关推荐

Python中如何使用logging模块记录日志

日志在实际生产工作中有着很重要的作用,之前一直不太注意这方面,导致生产环境遇到问题无从下手,借着整理把日志这块的功能熟悉下。网上有很多相关的介绍,不过还是建议大家浏览下官方相关的资料。官方文档的布局都差不多这里以3.8.12的版本为例:logging — Logging facility for Python — Python 3.8.12 documentation

文档对logging模块的功能整体上做了个简单的介绍,左边的红框说logging模块是线程安全的(进程不安全),如何解决多进程的问题在logging Cookbook(右边的红框)中有详细的介绍,也可以引入第三方包解决,后面会简单介绍下。

Basic Tutorial中有些基本的使用方法,Advanced Logging Tutorial中的LoggingFlow详细介绍了log日志信息的处理流程,简单理解就是logger负责生产日志,handle负责记录日志。

logging模块的使用有两种,一种是直接使用,一种是通过配置(python类或者是配置文件的方式这里归为一类)。这两种方法使用起来各有优点,直接使用配置会灵活些,创建响应的实例后可以直接修改属性,比如namer和suffix参数等等;配置文件的使用方式比较优雅,如果想做一些个性化的配置会比较麻烦些,可以自己创建对应的类来实现。

1、直接配置使用

2、使用配置文件

使用配置文件也有几种不同的格式,这里主要是想介绍字典类型的dictConfig(该例子在Logging Cookbook)的使用,你直接使用图片中的代码是会报错的,需要把里面的owner字段去掉(你的电脑可能并不存在这两个用户)。

这里还要额外说明下dicConfig()的参数要求,这些都可以在官方文档中找到,这里简单介绍下主要的几个点。

logging.config — Logging configuration — Python 3.10.5 documentation

1、version目前有效值为1(必要参数)。

后面的都是可选参数了:

2、‘()’代表自定义方法(实例)。

3、formatters格式化中定义日志相关的记录格式。

4、filters过滤器中定义日志过滤的条件,确认哪些日志需要保留。

5、handlers处理器中定义日志的输出方式,比如console控制台或者file文件以及输出日志的格式(format)。

6、loggers记录器中定义日志级别、过滤器以及日志处理器(handlers)。

7、root中进行根logger的配置,其配置可以被其他logger使用,可以理解为是父logger,其他的logger可以继承这个root的配置。所有的日志记录都会转发到root,如果logger中有等级配置,则这个转发的日志等级和root中的配置无关(root提供配置的继承)。由于有继承关系的存在,在大部分情况下同一个应用中并没有必要配置所有的logger。

8、incremental中进行额外配置的添加默认False。

9、disable_existing_loggers中设置非root-loggers的可用性(不包括loggingConfigure中配置的loggers),不配置默认为True。

logger中日志的级别具有几个特点:1、可以继承父类的日志级别。2、配置的日志级别是大于关系,配置了DEBUG实际是配置了大于DEBUG的日志级别,如果要精确输出某种日志级别需要单独实现。

注意:采用配置文件的方式时要注意,配置文件中自定义函数的参数一定要是初始化函数的入参,属性或者方法并不支持直接在配置文件中配置。

附上一个配置示例,配置文件中添加了输出到console的配置(如果是debug状态需要输出到console)

import logging, logging.config, osimport timeimport socketfrom logging.handlers import TimedRotatingFileHandlerimport logging.confighost_name = socket.gethostname()sys_name = 'system_name'# 获取当前脚本绝对路径sys_path = os.path.abspath(__file__)def owned_file_handler(log_level):# 获取当前路径作为日志存放路径log_dir = os.path.join(os.path.dirname(sys_path), 'logs')# 如果路径不存在创建对应路径if not os.path.exists(log_dir):os.makedirs(log_dir)# 文件命名规则file_name = os.path.join(log_dir, '{}_{}_{}.log'.format(sys_name, log_level, host_name))# 滚动备份7个日志每天凌晨进行备份# file_handler = TimedRotatingFileHandler(file_name, when='midnight', backupCount=7, interval=1, encoding='utf-8')# 这里为了测试间隔1秒保存两个日志文件file_handler = TimedRotatingFileHandler(file_name, when='S', backupCount=2, interval=1, encoding='utf-8')# 配置日志文件后缀,如果想使用默认的数量管理对日志进行管理,日志日期的后缀格式为S'%Y-%m-%d_%H-%M-%S'# file_handler.suffix = '%Y-%m-%d_%H-%M-%S.log'return file_handler# 添加debug函数用于调试的时候可以输出到consoledef get_debug(debug):file_filter = logging.Filter()file_filter.filter = lambda debug: Truereturn file_filter# 添加日志级别的过滤def owned_filter(log_levelno):file_filter = logging.Filter()file_filter.filter = lambda record: record.levelno == log_levelnoreturn file_filterLOGGING_SET = {'version': 1,'disable_existing_loggers': False,'formatters': {'default': {# 设置日志格式以及时间格式'format': '[%(asctime)s:%(msecs)03d][{}][{}][%(module)s][%(process)d][%(thread)d]''----[%(levelname)s]---------%(message)s'.format(host_name, sys_name),'datefmt': '%Y-%m-%d-%H-%M-%S'},},'filters': {# 这里根据是否需要输出到console的实际使用情况进行配置'require_debug_true': {'()': get_debug,'debug': True},# 配置INFO级别的filter'filter_info': {'()': owned_filter,'log_levelno': logging.INFO},# 配置ERROR级别的filter'filter_error': {'()': owned_filter,'log_levelno': logging.ERROR}},'handlers': {# 配置console输出'console': {'class': 'logging.StreamHandler','formatter': 'default','filters': ['require_debug_true'],},# 配置INFO级别的文件输出'file_info': {'()': owned_file_handler,'log_level': 'INFO','formatter': 'default','filters': ['filter_info']},# 配置ERROR级别的文件输出'file_error': {'()': owned_file_handler,'log_level': 'ERROR','formatter': 'default','filters': ['filter_error']}},# root可以获取所有日志信息,配置输出console,有必要的时候也可以配置输出到文件'root': {'handlers': ['console'],'level': 'DEBUG'},# 定义使用的logger:own_logger'loggers': {'own_logger': {'handlers': ['file_info', 'file_error'],},}}logging.config.dictConfig(LOGGING_SET)own_logger = logging.getLogger('own_logger')if __name__ == '__main__':for i in range(10):own_logger.debug('A debug message' * 10)own_logger.info('A info message' * 10)own_logger.error('A error message' * 10)time.sleep(1)

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。