赞
踩
日志记录对于软件开发调试和运行都非常重要。Python标准库提供了一个日志记录系统,可以很方便的在python项目中添加日志记录。本文将详细介绍如何使用python的 logging
模块来记录日志。
目录
基础使用 日志级别 基本配置 保存日志到文件 格式化输出 捕获异常信息自定义logger 日志模块四大组件 处理器 格式器 过滤器 示例其他配置方法 fileConfig()方法 dictConfig()方法 1. yaml配置文件 2. json配置文件
主要包括了5种日志级别,代表5种严重级别(严重程度由低到高):
DEBUG:提供详细的详细
INFO:程序运行的关键步骤信息
WARNING:警告信息
ERROR:程序错误,某个功能无法执行
CRITICAL:严重错误,可能整个程序无法执行
Logger提供了一个默认的记录器,称为root Logger。
import logging`` ``logging.debug('Debug 级别日志信息')``logging.info('Info 级别日志信息')``logging.warning('Warning 级别日志信息')``logging.error('Error 级别日志信息')``logging.critical('Critical 级别日志信息')
输出:
WARNING:root:Warning 级别日志信息``ERROR:root:Error 级别日志信息``CRITICAL:root:Critical 级别日志信息
默认打印WARNING及更高严重级别的日志。
可以使用basicConfig(**kwargs)
方法对日志系统进行配置。常用参数如下:
level: 指定严重级别。
filename: 指定文件。
filemode: 如果指定了filename,则以该模式打开文件。默认是a,表示追加。
a:追加
w:覆盖
format:日志信息的格式。默认levelname, name和message属性,用冒号分隔。
注意:basicConfig
函数只能被调用一次。
level参数可以设置要记录的日志消息的严重级别:
import logging`` ``logging.basicConfig(level=logging.DEBUG)`` ``logging.debug('Debug 级别日志信息')``logging.info('Info 级别日志信息')``logging.warning('Warning 级别日志信息')``logging.error('Error 级别日志信息')``logging.critical('Critical 级别日志信息')
输出:
DEBUG:root:Debug 级别日志信息``INFO:root:Info 级别日志信息``WARNING:root:Warning 级别日志信息``ERROR:root:Error 级别日志信息``CRITICAL:root:Critical 级别日志信息
import logging`` ``logging.basicConfig(filename='test.log', filemode='w', format='%(name)s - %(levelname)s - %(message)s')``logging.debug('Debug 级别日志信息')``logging.info('Info 级别日志信息')``logging.warning('Warning 级别日志信息')``logging.error('Error 级别日志信息')``logging.critical('Critical 级别日志信息')
format
参数用于格式化输出设置,除了默认设置levelname, name和message属性:
属性名 | 使用格式 | 描述 |
---|---|---|
asctime | %(asctime)s | 时间,默认格式为 ‘2003-07-08 16:49:45,896’ |
created | %(created)f | 时间戳 |
relativeCreated | %(relativeCreated)d | 相对于加载日志模块的时间(以毫秒为单位)。 |
msecs | %(msecs)d | 日志创建时间的毫秒部分 |
filename | %(filename)s | 脚本文件名称 |
funcName | %(funcName)s | 调用日志记录的函数名称 |
module | %(module)s | 脚本模块名 |
pathname | %(pathname)s | 脚本文件绝对路径名 |
name | %(name)s | 记录器名称,默认logger名为root |
levelname | %(levelname)s | 文本类型的日志级别 ('DEBUG' , 'INFO' , 'WARNING' , 'ERROR' , 'CRITICAL' ). |
levelno | %(levelno)s | 数字类型的日志级别 (10, 20, 30, 40, 50). |
lineno | %(lineno)d | 日志调用的代码所在行号 |
message | %(message)s | 日志信息 |
process | %(process)d | 进程ID |
processName | %(processName)s | 进程名称 |
thread | %(thread)d | 线程ID |
threadName | %(threadName)s | 线程名 |
其中 asctime
时间格式可以使用 datefmt
属性更改,语法格式与python datetime模块的格式化函数相同,例如:
import logging`` ``logging.basicConfig(level=logging.DEBUG, format='%(asctime)s - %(message)s', datefmt='%Y%m%d-%H:%M:%S')`` ``logging.debug('Debug 级别日志信息')``logging.info('Info 级别日志信息')``logging.warning('Warning 级别日志信息')``logging.error('Error 级别日志信息')``logging.critical('Critical 级别日志信息')
输出:
20230228-22:13:05 - Debug 级别日志信息``20230228-22:13:05 - Info 级别日志信息``20230228-22:13:05 - Warning 级别日志信息``20230228-22:13:05 - Error 级别日志信息``20230228-22:13:05 - Critical 级别日志信息
除了以上属性外,还支持自定义属性,使用 extra
参数传递:
import logging`` ``FORMAT = '%(asctime)s - %(clientip)s - %(message)s'``logging.basicConfig(format=FORMAT)``clientip = '192.168.0.1'``d = {'clientip':clientip}`` ``logging.info('Info 级别日志信息')``logging.warning('Warning 级别日志信息', extra=d)
输出:
2023-03-04 11:21:23,459 - 192.168.0.1 - Warning 级别日志信息
设置 exc_info
参数为 True
可以输出信息报错信息:
import logging`` ``try:` `res = 1 / 0``except Exception as e:` `logging.error(e, exc_info=True)
输出:
ERROR:root:division by zero``Traceback (most recent call last):` `File "d:\logging\log_demo3.py", line 4, in <module>` `res = 1 / 0``ZeroDivisionError: division by zero
也可以使用 logging.exception()
方法,效果一样:
logging.exception(e)
另外,stack_info
参数设置为 True
是可以打印堆栈信息。
可以通过创建logger类的对象来定义自己的记录器。
日志模块最常用的类:
Logger:公开了一个接口,代码通过使用该接口记录日志消息。
Handler:处理器,将logger创建的日志发送到目的地(控制台或文件)。常用的处理程序包括:
FileHandler:用于将日志消息发送到文件
StreamHandler:用于向输出流(如stdout)发送日志消息
SyslogHandler:用于向syslog守护进程发送日志消息
HTTPHandler:用于使用HTTP协议发送日志消息
Filter:过滤器,提供一种机制来确定记录哪些日志。
Formatter:格式器,决定日志消息的输出格式。
Logger类是入口,使用模块级别函数 logging.getLogger(name)
实例化,最终由Handler来对日志进行处理,Handler会调用Filter和Formatter来对日志进行过滤和格式化。
import logging`` ``logger = logging.getLogger('mylogger')`` ``logger.debug('Debug 级别日志信息')``logger.info('Info 级别日志信息')``logger.warning('Warning 级别日志信息')``logger.error('Error 级别日志信息')``logger.critical('Critical 级别日志信息')
自定义logger不能使用 basicConfig()
来配置,需要使用 处理器(Handler)和 格式器(Formatter)来配置。
可以使用处理器(Handler)来配置自定义logger将日志保存到文件、输出到控制台、通过HTTP发送或者通过邮件发送。
处理器也可以设置日志严重级别,为文件处理器(FileHandler
)和控制台处理器(StreamHandler
)设置不同的日志级别。
# 创建处理器 handlers``console_handler = logging.StreamHandler() # 输出到控制台``file_handler = logging.FileHandler(logname) # 输出到文件``console_handler.setLevel(logging.WARNING)``file_handler.setLevel(logging.ERROR)
格式器(Formatter)用来配置格式化输出。
# 创建格式器``console_format = logging.Formatter('%(name)s - %(levelname)s - %(message)s', '%Y%m%d-%H:%M:%S')``file_format = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s', '%Y%m%d-%H:%M:%S')
过滤器(Filter)可实现日志过滤操作,
import logging``import sys``import os`` ``class failureFilter(logging.Filter):` `def filter(self, record):` `if 'Failure' in record.msg:` `return True` `return False`` ``logger = logging.getLogger(__name__)` `console_handler = logging.StreamHandler(stream=sys.stdout) # 输出到控制台``# 添加filter``loggingFiletr = failureFilter()``console_handler.addFilter(loggingFiletr)`` ``logger.addHandler(console_handler)``logger.info('Info 级别日志信息')``logger.error('Failure')
自定义logger示例脚本:
import logging``import sys``import os`` ``class failureFilter(logging.Filter):` `def filter(self, record):` `if 'Failure' in record.msg:` `return True` `return False`` ``logger = logging.getLogger(__name__)``logger.setLevel(logging.INFO)`` ``abspath = os.path.dirname(os.path.abspath(__file__)) # 脚本绝对路径``logname = os.path.join(abspath, 'file.log')`` ``# 创建处理器 handlers``console_handler = logging.StreamHandler(stream=sys.stdout) # 输出到控制台``file_handler = logging.FileHandler(logname) # 输出到文件``console_handler.setLevel(logging.WARNING)``file_handler.setLevel(logging.ERROR)`` ``# 添加filter``loggingFiletr = failureFilter()``console_handler.addFilter(loggingFiletr)``file_handler.addFilter(loggingFiletr)`` ``# 创建格式器``console_format = logging.Formatter('%(name)s - %(levelname)s - %(message)s', '%Y%m%d-%H:%M:%S')``file_format = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s', '%Y%m%d-%H:%M:%S')`` ``# 将格式器添加到处理器中``console_handler.setFormatter(console_format)``file_handler.setFormatter(file_format)`` ``# 将处理器添加到logger``logger.addHandler(console_handler)``logger.addHandler(file_handler)`` ``logger.info('Info 级别日志信息')``logger.error('Failure')
除了前面介绍的 basicConfig()
方法、logger、handler和formatter来配置日志记录器外,还可以使用 fileConfig()
或 dictConfig()
方法来加载配置文件或字典实现日志记录器的配置。
配置文件(可使用configparser类读取)格式如下,此配置文件配置了控制台和文件输出两种方式:
[loggers]``keys=root,mylogger`` ``[handlers]``keys=consoleHandler,fileHandler`` ``[formatters]``keys=sampleFormatter`` ``[logger_root]``level=DEBUG``handlers=consoleHandler`` ``[logger_mylogger]``level=DEBUG``handlers=consoleHandler,fileHandler``qualname=mylogger``propagate=0`` ``[handler_consoleHandler]``class=StreamHandler``level=DEBUG``formatter=sampleFormatter``args=(sys.stdout,)`` ``[handler_fileHandler]``class=FileHandler``level=DEBUG``formatter=sampleFormatter``args=("config.log", "a")`` ``[formatter_sampleFormatter]``format=%(asctime)s - %(name)s - %(levelname)s - %(message)s``qualname=mylogger
使用 fileConfig
方法来加载配置:
import logging``import logging.config``import os`` ``abspath = os.path.dirname(os.path.abspath(__file__))` `confpath = os.path.join(abspath, 'logging.conf')`` ``if os.path.exists(confpath):` `logging.config.fileConfig(fname=confpath, disable_existing_loggers=False)`` ``# create logger``logger = logging.getLogger("mylogger")`` ``logger.debug('Debug 级别日志信息')``logger.info('Info 级别日志信息')
配置字典可以使用yaml或者json代码来编写。
创建logging.yaml
:
version: 1``formatters:` `simple:` `format: '%(asctime)s - %(name)s - %(levelname)s - %(message)s'` `datefmt: '%Y-%m-%d %H:%M:%S'``handlers:` `console:` `class: logging.StreamHandler` `level: INFO` `formatter: simple` `stream: ext://sys.stdout` `fileHandler:` `class: logging.FileHandler` `level: DEBUG` `formatter: simple` `filename: yaml.log` `encoding: utf8``loggers:` `mylogger:` `level: DEBUG` `handlers: [console,fileHandler]` `propagate: no``root:` `level: DEBUG` `handlers: [console]
调用示例:
import logging``import logging.config``import os``import yaml`` ``abspath = os.path.dirname(os.path.abspath(__file__))``confpath = os.path.join(abspath, 'logging.yaml')`` ``if os.path.exists(confpath):` `with open(confpath, 'r') as f:` `config = yaml.safe_load(f.read())` `logging.config.dictConfig(config)`` ``logger = logging.getLogger('mylogger')`` ``logger.debug('Debug 级别日志信息')``logger.info('Info 级别日志信息')
创建logging.json
:
{` `"version":1,` `"disable_existing_loggers":false,` `"formatters":{` `"simple":{` `"format":"%(asctime)s - %(name)s - %(levelname)s - %(message)s",` `"datefmt":"%Y-%m-%d %H:%M:%S"` `}` `},` `"handlers":{` `"console":{` `"class":"logging.StreamHandler",` `"level":"DEBUG",` `"formatter":"simple",` `"stream":"ext://sys.stdout"` `},` `"fileHandler":{` `"class":"logging.handlers.RotatingFileHandler",` `"level":"INFO",` `"formatter":"simple",` `"filename":"json.log",` `"maxBytes":10485760,` `"backupCount":10,` `"encoding":"utf8"` `}` `},` `"loggers":{` `"mylogger":{` `"level":"INFO",` `"handlers":["fileHandler"],` `"propagate":"no"` `}` `},` `"root":{` `"level":"INFO",` `"handlers":["console","fileHandler"]` `}``}
调用示例:
import logging``import logging.config``import os``import json`` ``abspath = os.path.dirname(os.path.abspath(__file__))` `confpath = os.path.join(abspath, 'logging.json')`` ``if os.path.exists(confpath):` `with open(confpath, 'r') as f:` `config = json.load(f)` `logging.config.dictConfig(config)`` ``logger = logging.getLogger("mylogger")`` ``logger.debug('Debug 级别日志信息')``logger.info('Info 级别日志信息')
点击下方安全链接前往获取
CSDN大礼包:《Python入门&进阶学习资源包》免费分享
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。