python模块详解 | logging
基础日志 - logging.basicConfig()
import logging
logging.basicConfig(
filename='document.log',
level=logging.INFO,
format="%(asctime)s %(pathname)s[%(lineno)s]%(levelname)s:%(message)s",
datefmt="%Y-%m-%d %H:%M:%S %p"
)
logging.info('记录到日志')
下面结合四个参数展开来聊一下,
1. filename
可选。保存到本地日志文件的文件名。
2. level
日志级别,各级别适用性如下(以严重性递增,DEBUG最低):
级别 | 优先级数值 | 何时使用 |
---|---|---|
DEBUG |
10 | 细节信息,仅当诊断问题时适用。 |
INFO |
20 | 确认程序按预期运行 |
WARNING |
30 | 表明有已经或即将发生的意外(例如:磁盘空间不足)。程序仍按预期进行 |
ERROR |
40 | 由于严重的问题,程序的某些功能已经不能正常执行 |
CRITICAL |
50 | 严重的错误,表明程序已不能继续执行 |
例:如果把日志记录级别设置为INFO,那么只有比日志是INFO或比INFO级别更高的日志,才会被记录到文件中
3. format
格式 | 描述 |
---|---|
%(name)s |
用于记录调用的日志记录器名称。 |
%(asctime)s |
字符串形式的当前时间。 默认形式为 ‘2003-07-08 16:49:45,896’ (逗号之后的数字为时间的毫秒部分) |
%(created)f |
当前时间(即 time.time() 的返回值) |
%(pathname)s |
发出日志记录调用的「源文件的完整路径名」(如果可用) |
%(filename)s |
发出日志记录调用的「源文件的文件名」 |
%(funcName)s |
调用日志输出函数的「函数名」 |
%(levelname)s |
消息文本记录级别 ('DEBUG' , 'INFO' , 'WARNING' , 'ERROR' , 'CRITICAL' ). |
%(levelno)s |
消息数字记录级别 (DEBUG , INFO , WARNING , ERROR , CRITICAL ). |
%(lineno)d |
发出日志记录调用所在的源代码「行号」(如果可用) |
%(message)s |
记入日志的消息 |
%(module)s |
调用日志输出函数的模块名 |
%(process)d |
进程ID,可能没有 |
%(thread)d |
线程ID,可能没有 |
例:"%(asctime)s %(pathname)s[%(lineno)s]%(levelname)s:%(message)s"
4. datefmt
-
作用:格式化当前时间(
%(asctime)s
) -
使用:用法参考
time.strftime(format)
中format参数的写法 -
例:
"%m-%d-%Y %H:%M:%S"
进阶日志 - logging.getLogger()
1. Logger(记录器)
创建记录器对象
logger = logging.getLogger()
每个程序在输出信息之前都要获得一个logger,logger通常对应了程序的模块名。
记录器常见的配置方法:
Logger.setLevel()
指定记录器将处理的最低严重性日志消息Logger.addHandler()
和Logger.removeHandler()
从记录器对象中添加和删除处理程序对象Logger.addFilter()
和Logger.removeFilter()
可以添加或移除记录器对象中的过滤器
2. Handler(处理程序)
https://docs.python.org/zh-cn/3.8/library/logging.handlers.html#watchedfilehandler
1. 创建处理程序对象,以下是一些常见的handler:
-
handler = logging.StreamHandler()
class logging.StreamHandler(stream=None)
StreamHandler
类位于核心logging
包,它可将日志记录输出发送到数据流例如 sys.stdout, sys.stderr 或任何文件类对象(或者更精确地说,任何支持write()
和flush()
方法的对象) -
handler = logging.FileHandler()
class logging.FileHandler(filename, mode=‘a’, encoding=None, delay=False)
FileHandler
类位于核心logging
包,它可将日志记录输出到磁盘文件中。 它从StreamHandler
继承了输出功能。 -
handler = logging.NullHandler()
NullHandler
类位于核心logging
包,它不执行任何格式化或输出。 它实际上是一个供库开发者使用的‘无操作’处理程序。 -
handler = logging.handlers.WatchedFileHandler()
WatchedFileHandler
类位于logging.handlers
模块,这个FileHandler
用于监视它所写入日志记录的文件。 如果文件发生变化,它会被关闭并使用文件名重新打开。 -
handler = logging.handlers.BaseRotatingHandler()
BaseRotatingHandler
类位于logging.handlers
模块中,它是轮换文件处理程序类RotatingFileHandler
和TimedRotatingFileHandler
的基类。 你不需要实例化此类,但它具有你可能需要重载的属性和方法。 -
handler = logging.handlers.RotatingFileHandler()
class logging.handlers.RotatingFileHandler(filename, mode=‘a’, maxBytes=0, backupCount=0, encoding=None, delay=False)
RotatingFileHandler
类位于logging.handlers
模块,它支持磁盘日志文件的轮换。可以管理文件大小,当文件达到一定大小之后,它会自动将当前日志文件改名,让后创建一个新的同名日志文件继续输出。 -
handler = logging.handlers.TimedRotatingFileHandler()
TimedRotatingFileHandler
类位于logging.handlers
模块,它支持基于「特定时间间隔」的磁盘日志文件轮换。class logging.handlers.TimedRotatingFileHandler(filename, when=‘h’, interval=1, backupCount=0, encoding=None, delay=False, utc=False, atTime=None)
-
filename - 日志文件的保存路径
-
interval - 时间间隔
-
when - 时间间隔的单位
值 间隔类型 如果/如何使用 atTime 'S'
秒 忽略 'M'
分钟 忽略 'H'
小时 忽略 'D'
天 忽略 'W0'-'W6'
工作日(0=星期一) 用于计算初始轮换时间 'midnight'
如果未指定 atTime 则在午夜执行轮换,否则将使用 atTime。 用于计算初始轮换时间 注:
- 如果选择 D-天,那么这个不是严格意义上的“天”,而是从你项目启动开始,过了24小时,才会重新新建一个新的日志文件,如果项目重启,这个时间就会重置。
- 如果选择“midnight”, 指的是过了午夜12点,就会创建新的日志。
-
例
handler = logging.handlers.TimedRotatingFileHandler(log_path, when='midnight', interval=3, backupCount=10, encoding="utf-8")
-
-
还有很多handler类型待发掘……
2. handler常见的配置方法:
-
handler.setLevel(level)
- 指定被处理信息的信息等级- level -
level = logging.INFO
- level -
-
handler.setFormatter(formatter)
- 设置format格式- formatter -
formatter = logging.Formatter(fmt, datefmt)
fmt参数的使用请参考:format
- formatter -
-
handler.addFilter(filter)/removeFilter(filter)
- 新增或删除一个filter对象-
filter
class IgnoreAssLogFilter(logging.Filter): # 忽略带ass的日志, def filter(self,record): return "ass" not in record.getMessage() handler.addFilter(IgnoreAssLogFilter())
-
3. logger + handler
import logging
# handler
handler = logging.FileHandler(filename="document.log")
handler.setLevel(logging.INFO)
handler.setFormatter(logging.Formatter('%(pathname)s %(message)s'))
# logger
logger = logging.getLogger('log')
logger.setLevel(logging.DEBUG)
logger.addHandler(handler) # 添加handler到logger
logger.info('我是日志内容,快把我记录下来')
import time
import logging
import logging.handlers
# formatter
formatter = logging.Formatter(
fmt='%(asctime)s %(filename)s[%(lineno)d] %(levelname)s %(message)s',
datefmt='%Y-%m-%d %H:%M:%S')
# handler
handler_log = logging.handlers.TimedRotatingFileHandler(
filename=f'{time.strftime("%Y-%m-%d")}.log',
when='midnight',
interval=1,
encoding='utf-8'
)
handler_log.setLevel(logging.DEBUG)
handler_log.setFormatter(formatter)
handler_error = logging.FileHandler(filename='error.log')
handler_error.setLevel(logging.ERROR)
handler_error.setFormatter(formatter)
handler_console = logging.StreamHandler()
handler_console.setLevel(logging.INFO)
handler_console.setFormatter(formatter)
# logger
log = logging.getLogger('RPA')
log.setLevel(logging.DEBUG)
log.addHandler(handler_log) # 日志文件
log.addHandler(handler_cs) # console窗口
log.info('欲买桂花同载酒,终不似,少年游。')