python中的Logging总结

基础概念

  • Logger
    • 向应用程序代码公开了几种方法(info等),以便应用程序可以在运行时记录消息。
    • 根据严重性(默认Filter)或自定义Filter确定要处理的日志消息。
    • 将相关的日志消息传递给所有感兴趣的Handler
    • 建议使用logging.getLogger(name)获取
    • Logger.addHandler()Logger.removeHandler()增删Handler
    • Logger.addFilter()Logger.removeFilter()增删Filter
  • LogRecord :日志记录器,将日志传到相应的处理器处理。
  • Handler :日志处理器, 将Logger生成的LogRecord发送至合适的目的地。
    • setLevel()每个Handler中设置的级别确定Handler将发送哪些消息。
    • setFormatter()选择一个该处理程序使用的Formatter对象。
    • addFilter()removeFilter() 分别在处理程序上配置和取消配置Filter对象。
  • Filter :过滤器, 提供了更好的粒度控制,它可以决定输出哪些日志记录。
  • Formatter:格式化器, 指明了最终输出中日志记录的布局。

记录流程:

image

日志级别

级别 数值 何时使用
CRITICAL 50 严重的错误,表明程序已不能继续执行
ERROR 40 由于严重的问题,程序的某些功能已经不能正常执行
WARNING 30 表明有已经或即将发生的意外(例如:磁盘空间不足)。程序仍按预期进行
INFO 20 确认程序按预期运行
DEBUG 10 细节信息,仅当诊断问题时适用。
NOTSET 0

注意

  • 默认级别是WARNING
  • Logger.exception()创建与 Logger.error() 相似的日志信息。 不同之处是, Logger.exception() 同时还记录当前的堆栈追踪。

基础使用

1
2
3
4
5
6
7
8
import logging

logging.basicConfig(filename="test.log", filemode="w", format="%(asctime)s %(name)s:%(levelname)s:%(message)s", datefmt="%d-%M-%Y %H:%M:%S", level=logging.DEBUG)
logging.debug('This is a debug message')
logging.info('This is an info message')
logging.warning('This is a warning message')
logging.error('This is an error message')
logging.critical('This is a critical message')

直接使用logging.xxx()实际上是使用了rootlogger

format细节

详见python官网

典型使用:

1
[日期 日志级别 源文件 行号 进程号] 日志信息
1
[ %(asctime)-15s %(levelname)s %(filename)15s:%(lineno)-4d pid:%(process)-5d]  %(message)s"

进阶使用

Logger层级

在命名记录器时使用的一个好习惯是在每个使用日志记录的模块中使用模块级记录器,命名如下:

1
logger = logging.getLogger(__name__)

这意味着记录器名称跟踪包或模块的层次结构,并且直观地从记录器名称显示记录事件的位置。记录器层次结构的根称为根记录器。根记录器的名称在记录的输出中打印为’root’ 。

好用的Handler

官方提供了很多有用的Handler在这里查看

如果需要将每天的日志分文件保存,并在日志文件上带有日期信息的话,可以这样:

1
2
3
4
5
from logging.handlers import TimedRotatingFileHandler
logname = "my_app.log"
handler = TimedRotatingFileHandler(logname, when="midnight", interval=1)
handler.suffix = "%Y%m%d"
logger.addHandler(handler)

分割日志用先往默认的文件(my_app.log)里打,等到分割条件的时候,把之前打的那部分日志转移到对应的分割文件里。

获得某个package里所有的logger

1
2
3
import logging

loggers = [logging.getLogger(name) for name in logging.root.manager.loggerDict]

关闭第三方package的logger

1
2
3
import logging

logging.getLogger("urllib3").setLevel(logging.WARNING)

参考资料

官方文档:

不错的博客:

默认的root logger:

使用gunicorn和flask时: