pythonlogging⽇志处理详解
⽂章⽬录
1.介绍
在 Python 中有⼀个标准的 logging 模块,我们可以使⽤它来进⾏标注的⽇志记录,利⽤它我们可以更⽅便地进⾏⽇志记录,同时还可以做更⽅便的级别区分以及⼀些额外⽇志信息的记录,如时间、运⾏模块信息等。
1.1 架构
整个⽇志记录的框架可以分为这么⼏个部分:
Logger 记录器,暴露了应⽤程序代码能直接使⽤的接⼝。
Handler 处理器,将(记录器产⽣的)⽇志记录发送⾄合适的⽬的地。
Filter 过滤器,提供了更好的粒度控制,它可以决定输出哪些⽇志记录。
Formatter 格式化器,指明了最终输出中⽇志记录的布局。
1.1.1 Logger 记录器
Logger是⼀个树形层级结构,在使⽤接⼝debug,info,warn,error,critical之前必须创建Logger实例,即创建⼀个记录器,如果没有显式的进⾏创建,则默认创建⼀个root logger,并应⽤默认的⽇志级别(WARN),处理器Handler(StreamHandler,即将⽇志信息打印输出在标准输出上),和格式化器Formatter(默认的格式即为第⼀个简单使⽤程序中输出的格式)。
创建⽅法:
logger = Logger(logger_name)
创建Logger实例后,可以使⽤以下⽅法进⾏⽇志级别设置,增加处理器Handler。
logger.setLevel(logging.ERROR)#设置⽇志级别为ERROR,即只有⽇志级别⼤于等于ERROR的⽇志才会输出
logger.addHandler(handler_name)# 为Logger实例增加⼀个处理器
1.1.2 Handler 处理器
Handler处理器类型有很多种,⽐较常⽤的有三个,StreamHandler,FileHandler,NullHandler。
创建StreamHandler之后,可以通过使⽤以下⽅法设置⽇志级别,设置格式化器Formatter,增加或删除过滤器Filter。
ch.setLevel(logging.WARN)#指定⽇志级别,低于WARN级别的⽇志将被忽略
ch.setFormatter(formatter_name)#设置⼀个格式化器formatter
ch.addFilter(filter_name)#增加⼀个过滤器,可以增加多个
StreamHandler
创建⽅法:
sh = logging.StreamHandler(stream=None)
FileHandler
创建⽅法:
fh = logging.FileHandler(filename, mode='a', encoding=None, delay=False)
NullHandler
NullHandler类位于核⼼logging包,不做任何的格式化或者输出。
本质上它是个“什么都不做”的handler,由库开发者使⽤。
logging 模块提供的 全部Handler 有:
StreamHandler:logging.StreamHandler;⽇志输出到流,可以是 sys.stderr,sys.stdout 或者⽂件。
FileHandler:logging.FileHandler;⽇志输出到⽂件。
BaseRotatingHandler:logging.handlers.BaseRotatingHandler;基本的⽇志回滚⽅式。
RotatingHandler:logging.handlers.RotatingHandler;⽇志回滚⽅式,⽀持⽇志⽂件最⼤数量和⽇志⽂件回滚。
TimeRotatingHandler:logging.handlers.TimeRotatingHandler;⽇志回滚⽅式,在⼀定时间区域内回滚⽇志⽂件。
SocketHandler:logging.handlers.SocketHandler;远程输出⽇志到TCP/IP sockets。
DatagramHandler:logging.handlers.DatagramHandler;远程输出⽇志到UDP sockets。
SMTPHandler:logging.handlers.SMTPHandler;远程输出⽇志到邮件地址。
SysLogHandler:logging.handlers.SysLogHandler;⽇志输出到syslog。
NTEventLogHandler:logging.handlers.NTEventLogHandler;远程输出⽇志到Windows NT/2000/XP
的事件⽇志。
MemoryHandler:logging.handlers.MemoryHandler;⽇志输出到内存中的指定buffer。
HTTPHandler:logging.handlers.HTTPHandler;通过”GET”或者”POST”远程输出到HTTP服务器。
1.1.3 Formatter 格式化器
使⽤Formatter对象设置⽇志信息最后的规则、结构和内容,默认的时间格式为%Y-%m-%d %H:%M:%S。
创建⽅法:
formatter = logging.Formatter(fmt=None, datefmt=None)
其中,fmt是消息的格式化字符串,datefmt是⽇期字符串。如果不指明fmt,将使⽤’%(message)s’。如果不指明datefmt,将使⽤ISO8601⽇期格式。
1.1.4 Filter 过滤器
Handlers和Loggers可以使⽤Filters来完成⽐级别更复杂的过滤。Filter基类只允许特定Logger层次以下
的事件。例如⽤‘A.B’初始化的Filter允许Logger ‘A.B’, ‘A.B.C’, ‘A.B.C.D’, ‘A.B.D’等记录的事件,logger‘A.BB’, ‘B.A.B’ 等就不⾏。 如果⽤空字符串来初始化,所有的事件都接受。
创建⽅法:
filter= logging.Filter(name='')
熟悉了这些概念之后,有另外⼀个⽐较重要的事情必须清楚,即Logger是⼀个树形层级结构;
Logger可以包含⼀个或多个Handler和Filter,即Logger与Handler或Fitler是⼀对多的关系;
⼀个Logger实例可以新增多个Handler,⼀个Handler可以新增多个格式化器或多个过滤器,⽽且⽇志级别将会继承。
2. 优点
总的来说 logging 模块相⽐ print 有这么⼏个优点:
可以在 logging 模块中设置⽇志等级,在不同的版本(如开发环境、⽣产环境)上通过设置不同的输出等级来记录对应的⽇志,⾮常灵活。
print 的输出信息都会输出到标准输出流中,⽽ logging 模块就更加灵活,可以设置输出到任意位置,如写⼊⽂件、写⼊远程服务器等。
logging 模块具有灵活的配置和格式化功能,如配置输出当前模块信息、运⾏时间等,相⽐ print 的字符串格式化更加⽅便易⽤。3. ⽤法
3.1 默认输出
⾼于WARNING的⽇志信息才会输出
$ cat log1.py
import logging
logging.basicConfig()
logging.debug('This is a debug message')
logging.info('This is an info message')
logging.warning('This is a warning message')
<('This is an error message')
输出:
$ python log1.py
WARNING:root:This is a warning message
ERROR:root:This is an error message
CRITICAL:root:This is a critical message
3.2 ⽇志配置格式输出
配置⽅式
显式创建记录器Logger、处理器Handler和格式化器Formatter,并进⾏相关设置;
通过简单⽅式进⾏配置,使⽤basicConfig()函数直接进⾏配置;
通过配置⽂件进⾏配置,使⽤fileConfig()函数读取配置⽂件;
通过配置字典进⾏配置,使⽤dictConfig()函数读取配置信息;
通过⽹络进⾏配置,使⽤listen()函数进⾏⽹络配置。
basicConfig关键字参数
关键字描述
filename 创建⼀个FileHandler,使⽤指定的⽂件名,⽽不是使⽤StreamHandler。
filemode 如果指明了⽂件名,指明打开⽂件的模式(如果没有指明filemode,默认为'a')。
format handler使⽤指明的格式化字符串。
datefmt 使⽤指明的⽇期/时间格式。
level 指明根logger的级别。
stream 使⽤指明的流来初始化StreamHandler。该参数与'filename'不兼容,如果两个都有,'stream'被忽略。format格式
格式描述
%(levelno)s 打印⽇志级别的数值
%(levelname)s 打印⽇志级别名称
%(pathname)s 打印当前执⾏程序的路径
%(filename)s 打印当前执⾏程序名称
%(funcName)s 打印⽇志的当前函数
%(lineno)d 打印⽇志的当前⾏号
%(asctime)s 打印⽇志的时间
%(thread)d 打印线程id
%(threadName)s 打印线程名称
%(process)d 打印进程ID
%(message)s 打印⽇志信息
3.2.1 配置输出级别并指定到⽂件
$ cat log2.py
#!/usr/local/bin/python
# -*- coding:utf-8 -*-
import logging
# 通过下⾯的⽅式进⾏简单配置输出⽅式与⽇志级别
logging.basicConfig(filename='logger.log', level=logging.INFO)
logging.debug('debug message')
logging.info('info message')
logging.warn('warn message')
<('error message')
输出:
$ python log2.py
$ cat logger.log
INFO:root:info message #info级别也能输出
WARNING:root:warn message
ERROR:root:error message
CRITICAL:root:critical message
3.2.2 声明了⼀个 Logger 对象,它就是⽇志输出的主类
$ cat log3.py
#!/usr/local/bin/python
# -*- coding:utf-8 -*-
import logging
# 通过下⾯的⽅式进⾏简单配置输出⽅式与⽇志级别
logging.basicConfig(filename='logger.log', level=logging.INFO)
logger = Logger(__name__)
logger.debug('debug message')
logger.info('info message')
logger.warn('warn message')
<('error message')
输出:
$ python log3.py
$ cat logger.log
INFO:__main__:info message
WARNING:__main__:warn message
ERROR:__main__:error message
CRITICAL:__main__:critical message
3.2.3 格式化输出
$ cat log4.py
import logging
logging.basicConfig(filename="logger.log", filemode="w",format="%(asctime)s %(name)s:%(levelname)s:%(message)s", datefmt="%d-%M-%Y %H:%M:%S ", level=logging.DEBUG)
logger = Logger(__name__)
logger.debug('debug message')
logger.info('info message')
logger.warn('warn message')
<('error message')
输出:
$ python log4.py
$ cat logger.log
17-49-202013:49:16 __main__:DEBUG:debug message
17-49-202013:49:16 __main__:INFO:info message
17-49-202013:49:16 __main__:WARNING:warn message
17-49-202013:49:16 __main__:ERROR:error message
python格式化输出format17-49-202013:49:16 __main__:CRITICAL:critical message
3.3 Handler配置
3.3.1 handler配置格式输出
$ cat log5.py
import logging
logger = Logger(__name__)
logger.setLevel(level=logging.INFO)
handler = logging.FileHandler('output.log')
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
handler.setFormatter(formatter)
logger.addHandler(handler)
logger.info('This is a log info')
logger.debug('Debugging')
logger.warning('Warning exists')
logger.info('Finish')
没有再使⽤ basicConfig 全局配置,⽽是先声明了⼀个 Logger 对象,然后指定了其对应的 Handler 为
FileHandler 对象,然后Handler 对象还单独指定了 Formatter 对象单独配置输出格式,最后给 Logger 对象添加对应的 Handler 即可,最后可以发现⽇志就会被输出到 output.log 中.
$ python log5.py
$ cat output.log
2020-05-1713:58:41,039- __main__ - INFO - This is a log info
2020-05-1713:58:41,039- __main__ - WARNING - Warning exists
2020-05-1713:58:41,039- __main__ - INFO - Finish
2020-05-1714:01:15,909- __main__ - INFO - This is a log info
2020-05-1714:01:15,909- __main__ - WARNING - Warning exists
2020-05-1714:01:15,909- __main__ - INFO - Finish
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论