一、日志级别
等级 | 数值 | 描述 |
---|---|---|
CRITICAL | 50 | 严重错误,程序不能正常运行。 |
FATAL | 50 | 同 CRITICAL。 |
ERROR | 40 | 错误,程序的某些功能不能正常运行。 |
WARNING | 30 | 警告,表明已经或即将发生的意外(例如:磁盘空间不足),但程序仍按照预期运行。 |
WARN | 30 | 同 WARNING。 |
INFO | 20 | 关键信息,程序按照预期运行。 |
DEBUG | 10 | 详细信息,在我们调试程序时使用。 |
NOTSET | 0 | 不设置。 |
默认的级别的WARNING
,意味着只会追踪该级别及以上的事件,除非更改日志配置。
二、logging.basicConfig(**kwargs)
参数 | 描述 |
---|---|
filename | 指定输出日志的文件名,如果指定了这个参数,实际上会启用FileHandler ,而不再是StreamHandler ,这样日志就输出到文件,而不输出到控制台了。 |
filemode | 指定文件打开模式,默认模式为“a”。 |
format | 指定日志信息的输出格式,参数说明如下: %(name)s:Logger的名称,默认为“root”。 %(levelno)s:数字类型的日志级别。 %(levelname)s:文本类型的日志级别。 %(pathname)s:调用日志输出函数的模块的完整路径。 %(filename)s:调用日志输出函数的模块的文件名。 %(module)s:调用日志输出函数的模块名。 %(lineno)d:调用日志输出函数的语句所在的代码行。 %(funcName)s:调用日志输出函数的函数名。 %(created)f:当前时间,用 UNIX 标准的表示时间的浮点数表示。 %(asctime)s:字符串形式的当前时间,默认格式是“2023-08-28 14:02:26,719”,逗号后面的是毫秒。 %(msecs)d:%(asctime)s 的毫秒部分。 %(relativeCreated)d:自 Logger 创建以来的毫秒数。 %(thread)d:线程 ID。 %(threadName)s:线程名称。 %(process)d:进程 ID。 %(processName)s:进程名称。 %(message)s:日志信息。 |
detefmt | 指定日期/时间的输出格式,与 time.strftime()所接受的格式相同。 |
style | Python 3.2 版本新增参数。指定 format 格式字符串的风格。“%”,“{”或“$”分别对应于 printf-style,str.format()或 string.Template。默认为“%”。 |
level | 指定日志级别。 |
stream | 指定数据流初始化StreamHandler ,例如:sys.stderr 、sys.stdout 或任何file-like 对象,默认为sys.stderr 。注意此参数与 filename 不兼容,如果两者同时存在,则会引发ValueError 。 |
handlers | Python 3.3 版本新增参数。指定日志处理时所使用的 Handler,必须是可迭代的对象。注意此参数与 filename 或 stream 不兼容,如果两者同时存在,则会引发ValueError 。 |
force | Python 3.8 版本新增参数。指定是否删除其它 Handler。 |
encoding | Python 3.9 版本新增参数。指定日志输出文件的编码格式。 |
errors | Python 3.9 版本新增参数。指定编码格式错误的处理方式,默认为“backslashreplace”。 |
示例:
import logging
import sys
def basic_config():
# 日志信息的输出格式
fmt = '%(name)s-%(levelno)s-%(levelname)s-%(pathname)s-%(filename)s-%(module)s-%(lineno)d-%(funcName)s-%(created)f-%(asctime)s-%(msecs)d-%(relativeCreated)d-%(thread)d-%(threadName)s-%(process)d-%(processName)s-%(message)s'
# 将日志输出到控制台 StreamHandler
stream_handler = logging.StreamHandler(sys.stdout)
# 将日志输出到文件 FileHandler
file_handler = logging.FileHandler('all.log', mode='w', encoding='utf-8')
# 日志配置
logging.basicConfig(format=fmt, datefmt='%Y/%m/%d %H:%M:%S', level='INFO', handlers=[stream_handler, file_handler])
# force 默认为 False,配置信息以上一条为准,force=True 时,配置信息以下面这条为准
logging.basicConfig(format=fmt, datefmt='%Y/%m/%d %H:%M:%S', level='ERROR', handlers=[stream_handler, file_handler], force=True)
# 日志信息
logging.critical('严重错误...')
logging.error('错误...')
logging.warning('警告...')
logging.info('关键信息...')
logging.debug('详细信息...')
if __name__ == '__main__':
basic_config()
运行结果:
D:\Python39\python.exe D:/JetBrains/PycharmProjects/python-logging/basicConfig_demo.py
root-50-CRITICAL-D:\JetBrains\PycharmProjects\python-logging\basicConfig_demo.py-basicConfig_demo.py-basicConfig_demo-19-basic_config-1693216745.661029-2023/08/28 17:59:05-661-217-3152-MainThread-18872-MainProcess-严重错误...
root-40-ERROR-D:\JetBrains\PycharmProjects\python-logging\basicConfig_demo.py-basicConfig_demo.py-basicConfig_demo-20-basic_config-1693216745.661029-2023/08/28 17:59:05-661-217-3152-MainThread-18872-MainProcess-错误...
Process finished with exit code 0
三、logging 模块的四种对象
对象 | 描述 |
---|---|
Logger | 日志生成器,产生日志的对象。1 个 Logger 对象可以绑定多个 Handler,用以输出至不同位置。 |
Filter | 日志过滤器,过滤日志的对象。 |
Handler | 日志处理器,处理日志的对象。对日志进行格式化,并输出到指定位置。 |
Formatter | 处理日志的格式。 |
一条日志完整的生命周期:
1.由 Logger 产生日志 -> 2.交给过滤器判断是否被过滤 -> 3.将日志消息分发给绑定的所有处理器 -> 4.处理器按照绑定的格式化对象输出日志
3.1 Logger 对象相关方法
方法 | 描述 |
---|---|
Logger.setLevel() | 指定日志级别。 |
Logger.addFilter() | 为 Logger 对象添加一个 Filter 对象。 |
Logger.removeFilter() | 为 Logger 对象移除一个 Filter 对象。 |
Logger.addHandler() | 为 Logger 对象添加一个 Handler 对象。 |
Logger.removeHandler() | 为 Logger 对象移除一个 Handler 对象。 |
Logger.critical() | 创建一条 CRITICAL 级别的日志。 |
Logger.error() | 创建一条 ERROR 级别的日志。 |
Logger.warning() | 创建一条 WARNING 级别的日志。 |
Logger.info() | 创建一条 INFO 级别的日志。 |
Logger.debug() | 创建一条 DEBUG 级别的日志。 |
Logger.exception() | 创建一条类似 ERROR 级别的日志。 |
Logger.log() | 创建一条指定级别的日志。 |
3.2 Handler 对象相关方法
方法 | 描述 |
---|---|
Handler.setLevel() | 指定日志级别。 |
Handler.setFormatter() | 为 Handler 对象设置一个 Formatter 对象。 |
Handler.addFilter() | 为 Handler 对象添加一个 Filter 对象。 |
Handler.removeFilter() | 为 Handler 对象移除一个 Filter 对象。 |
3.3 Handler 对象相关子类
子类 | 描述 |
---|---|
logging.StreamHandler | 将日志输出到数据流,例如:sys.stderr 、sys.stdout 或任何file-like 对象,默认为sys.stderr 。 |
logging.FileHandler | 将日志输出到文件。 |
logging.NullHandler | 不执行任何格式化或输出,它实际上是一个供库开发者使用的“无操作”处理程序。 |
logging.handlers.RotatingFileHandler | 日志按指定的文件大小轮换。 |
logging.handlers.TimedRotatingFileHandler | 日志按指定的时间间隔轮换。 |
logging.handlers.SocketHandler | 将日志输出到网络套接字。基类所使用的是 TCP 套接字。 |
logging.handlers.DatagramHandler | 它继承自SocketHandler ,将日志输出到网络套接字。基类所使用的是 UDP 套接字。 |
logging.handlers.SMTPHandler | 将日志发送到邮箱。 |
logging.handlers.SysLogHandler | 将日志发送到远程或本地 Unix syslog。 |
logging.handlers.MemoryHandler | 在内存中缓冲日志,并定期将其刷新到 target 处理程序中。刷新会在缓冲区满的时候,或是在遇到特定或更高严重程度事件的时候发生。 |
logging.handlers.HTTPHandler | 使用GET 或POST 将日志发送到 Web 服务器。 |
示例:
import logging
import sys
# 自定义过滤器并设置过滤条件
class CustomFilter(logging.Filter):
# 忽略包含 test 的日志
def filter(self, record) -> bool:
# print(record.getMessage())
return 'test' not in record.getMessage()
def stream_and_file_handler():
# 创建日志生成器 Logger
logger = logging.getLogger('logger')
# 设置 Logger 对象日志级别
logger.setLevel(level='DEBUG')
# 创建日志处理器 StreamHandler 将日志输出到控制台
stream_handler = logging.StreamHandler(sys.stdout)
# 创建日志处理器 FileHandler 将日志输出到文件
file_handler = logging.FileHandler('all.log', mode='w', encoding='utf-8')
# 设置 Handler 对象日志级别。Handler 对象日志级别应高于 Logger 对象日志级别,否则,设置 Handler 对象日志级别是没有意义的。
stream_handler.setLevel(level='INFO')
file_handler.setLevel(level='INFO')
# 实例化过滤器 Filter
custom_filter = CustomFilter()
# 将过滤器添加到处理器
stream_handler.addFilter(custom_filter)
file_handler.addFilter(custom_filter)
# 创建日志格式器 Formatter
stream_fmt = logging.Formatter(fmt='%(asctime)s-%(levelname)s-%(pathname)s-%(funcName)s-%(lineno)d-%(message)s')
file_fmt = logging.Formatter(fmt='%(asctime)s-%(name)s-%(levelname)s-%(pathname)s-%(funcName)s-%(lineno)d-%(process)d-%(processName)s-%(thread)d-%(threadName)s-%(message)s')
# 设置处理器的日志格式
stream_handler.setFormatter(stream_fmt)
file_handler.setFormatter(file_fmt)
# 将处理器添加到 Logger 对象
logger.addHandler(stream_handler)
logger.addHandler(file_handler)
# 输出日志
logger.critical('严重错误...')
logger.error('错误...')
logger.warning('警告...')
logger.info('关键信息...')
logger.debug('详细信息...')
logger.info('test message...')
logger.info('This is a test message...')
if __name__ == '__main__':
stream_and_file_handler()
运行结果:
D:\Python39\python.exe D:/JetBrains/PycharmProjects/python-logging/logging_demo.py
2023-08-29 18:27:58,921-CRITICAL-D:\JetBrains\PycharmProjects\python-logging\logging_demo.py-stream_and_file_handler-40-严重错误...
2023-08-29 18:27:58,921-ERROR-D:\JetBrains\PycharmProjects\python-logging\logging_demo.py-stream_and_file_handler-41-错误...
2023-08-29 18:27:58,921-WARNING-D:\JetBrains\PycharmProjects\python-logging\logging_demo.py-stream_and_file_handler-42-警告...
2023-08-29 18:27:58,921-INFO-D:\JetBrains\PycharmProjects\python-logging\logging_demo.py-stream_and_file_handler-43-关键信息...
Process finished with exit code 0
四、日志轮换
4.1 日志按指定的文件大小轮换
logging.handlers.RotatingFileHandler(filename, mode=‘a’, maxBytes=0, backupCount=0, encoding=None, delay=False, errors=None)
参数 | 描述 |
---|---|
filename | 指定输出日志的文件名。Python 3.6 以及之后版本除了字符串值,也接受 Path 对象作为 filename 参数。 |
mode | 指定文件打开模式,默认模式为“a”。 |
maxBytes | 指定文件大小,单位为字节。当即将超出指定大小时,将关闭旧文件并打开一个新文件用于输出。 |
backupCount | 指定备份文件数量,多了就会把最旧的那个文件删除。注意如果 maxBytes 或 backupCount 两者之一的值为零,就不会发生轮换。 |
encoding | 指定日志输出文件的编码格式。 |
delay | 如果 delay 为 True,则文件打开会被推迟至第一次调用emit() 的时候。默认情况下,文件会无限增长。 |
errors | Python 3.9 版本新增参数。指定编码格式错误的处理方式。 |
4.2 日志按指定的时间间隔轮换
logging.handlers.TimedRotatingFileHandler(filename, when=‘h’, interval=1, backupCount=0, encoding=None, delay=False, utc=False, atTime=None, errors=None)
参数 | 描述 |
---|---|
filename | 指定输出日志的文件名。Python 3.6 以及之后版本除了字符串值,也接受 Path 对象作为 filename 参数。 |