Python Logging模块

本文详细介绍了Python内置的Logging模块,包括日志级别(DEBUG, INFO, WARNING, ERROR, CRITICAL)、基本使用方法、日志输出到文件、记录变量数据、日志格式定制、时间显示以及进阶的Logger、Handler、Filter和Formatter四大组件的使用。通过实例展示了如何配置和使用日志记录器、处理器和格式化程序,以及如何实现日志的多目的地输出。
摘要由CSDN通过智能技术生成

简介

在Python中,提供了Logging模块用来记录日志,可以实现多种日志输出的形式,比如:控制台·、文件以及邮件等。

日志级别

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

直接使用Logging模块的方法

简单的例子

import logging
logging.warning('Wathch outQ')
# 默认级别是WARNING,所以info不会输出
logging.info('i told you so')

默认日志级别是WARNING,所以下面的info不会打印

记录日志到文件

import logging

logging.basicConfig(filename='example.log', level=logging.DEBUG)
logging.debug('a debug log')
logging.info('a info log')
logging.warning('a warning log')

# example.log
DEBUG:root:a debug log
INFO:root:a info log
WARNING:root:a warning log
logging.basicConfig(filename='example.log', filemode='w', level=logging.DEBUG)

可以通过指定filemode属性来控制日志打印是追加还是重新开始

记录变量数据

要记录变量数据的话,使用格式字符串作为占位符,并将数据作为参数

import logging
logging.warning('%s before you %s', 'Look', 'leap!')

日志记录格式

通过format参数可以指定要使用的格式

import logging
logging.basicConfig(format='%(levelname)s:%(message)s', level=logging.DEBUG)
logging.debug('This message should appear on the console')
logging.info('So should this')
logging.warning('And this, too')

format中可以使用的所有字符串,参考:LogRecord 属性

在日志中显示时间

可以在format字符串里用'%(asctime)s'

import logging
logging.basicConfig(format='%(asctime)s %(message)s')
logging.warning('is when this event was logged.')

# result
2010-12-12 11:41:42,612 is when this event was logged.

自定义时间显示格式,可以使用baseConfigdatafmt参数

import logging
logging.basicConfig(format='%(asctime)s %(message)s', datefmt='%m/%d/%Y %I:%M:%S %p')
logging.warning('is when this event was logged.')

# result
12/12/2010 11:46:36 AM is when this event was logged.

进阶使用

Logging模块分为四大组件:

  1. Logger(记录器):暴露了代码直接调用的接口。
  2. Handler(处理器):将日志记录发送到适当的目标(文件、控制台等)。
  3. Filter(过滤器):提供更精细的附加功能,用于确定要输出的日志记录。
  4. Formatter(格式化器):指定最终输出的日志样式。

日志信息存储在LogRecord实例中,并在Logger、Handler、Filter和Formatter之间传递

每个Logger都有一个名字,而且通过名字中包含.,可以实现Logger的继承关系,比如oss就是oss.env的父级,而且oss.env这个logger可以继承oss这个logger的LevelHandler

default_logger = logging.getLogger('oss')
...
logger = logging.getLogger('oss.env')

在每个使用日志记录的模块中使用模块级记录器,命名如下:

logger = logging.getLogger(__name__)

Logger存在一个根记录器,Logging.debug()Logging.info()这种直接调用Logging模块的方法使用的就是根记录器,根记录器的nameroot

可以将日志记录到不同的地方,目标由handler类提供,一个logger可以添加多个handler

记录流程

 

 

Logger的流程:

首先在调用logger记录日志的时候,就会根据level决定是否生成LogRecord对象实例

创建实例后,再根据Filter过滤log信息

之后先将实例传给handler,同时判断是否需要传递给父级的logger

Handler的流程:

判断Handler的日志级别

根据Handler的Filter过滤信息

最后格式化输出

Logger 记录器

Logger有三大任务,首先是暴露给代码一些方法,在需要记录日志的时候进行调用,其次是根据严重性(默认过滤工具)或Filter对象确定要处理的日志消息。第三,记录器将日志消息传给所有感兴趣的Handler

记录器上使用最多的方法分为两类,配置和日志记录

配置方法:

  • Logger.setLevel()指定记录器处理的最低日志级别。
  • Logger.addHandler()Logger.removeHandler()从记录器对象中添加或删除处理器对象
  • Logger.addFilter()Logger.removeFilter(),从记录器中添加或删除过滤器对象

不用在每个Logger上进行配置,可以通过记录器的继承关系来减少配置

日志记录方法:

  • Logger.debug()Logger.info()等方法都创建日志记录,包含消息和各自对应的级别。该消息实际上是一个格式化字符串,它可能包含标题字符串替换语法 %s 、 %d 、 %f 等等。其余参数是与消息中的替换字段对应的对象列表。
  • Logger.exception()创建和Logger.error()类似的异常信息。不同的是,Logger.exception()同时记录当前堆栈信息。仅在异常处理程序中调用此方法
  • Logger.log()将日志级别作为显式参数,是自定义日志级别的方法

getLogger()方法返回指定名称的Logger实例,如果未指定的话返回root。名称是以句点分隔的层次结构。有名字的Logger是单例的,所以多次调用getLogger()返回的是对同一Logger对象的引用。在继承关系中,低级别的logger是高级别logger的子级,比如有一个名为oss的Logger,那么oss.envoss.publish.sit都是oss的子级

Logger有有效等级的概念。如果没有在logger上显式指定level,那么将用其父级的level。如果父级也没有,那么接着向上找。最终的root是有默认级别WARNING

子logger将消息传播到与其上级logger关联的handler。因此,不必为应用程序使用的所有记录器定义和配置处理程序。为顶级记录器配置处理程序并根据需要创建子记录器就足够了。(但是,你可以通过将记录器的 propagate 属性设置 False 来关闭传播。)

# 举例
import logging
# 创建父级Logger,设置级别为DEBUG
default_logger = logging.getLogger('parent')
default_logger.setLevel(logging.DEBUG)
formatter = logging.Formatter(
    '%(asctime)s - %(name)20s - %(levelname)8s - %(message)s')
# 创建一个用于console的handler,设置级别为INFO
ch = logging.StreamHandler()
ch.setLevel(logging.INFO)
ch.setFormatter(formatter)
default_logger.addHandler(ch)

# 创建子Logger,增加FileHandler
child_logger = logging.getLogger('parent.child')
fh = logging.FileHandler('aaa.log')
fh.setLevel(logging.DEBUG)
fh.setFormatter(formatter)
child_logger.addHandler(fh)

child_logger.debug('a debug log')
child_logger.info('a info log')
child_logger.warning('a warning log')
child_logger.error('a error log')
child_logger.critical('a critical log')

# result
# 控制台和aaa.log内都记录了日志,因为子Logger会将消息传到父Logger的Handler,所以也能在控制台输出日志

Handler 处理程序

Handler根据日志级别将日志消息发送给指定目标(文件,控制台等)。Logger可以添加多个Handler,来实现将日志同时输出到控制台和文件,以及将严重错误日志发送到邮箱等。

主要使用的两个Handler是StreamHandlerFileHandler

配置方法:

  • setLevel() 方法,就像在记录器对象中一样,指定将被分派到适当目标的最低严重性。为什么有两个 setLevel() 方法?Logger中设置的级别确定将传递给其处理程序的消息的严重性。每个Handler中设置的级别确定处理程序将发送哪些消息。
  • [setFormatter()](<https://docs.python.org/zh-cn/3.8/library/logging.html#logging.Handler.setFormatter>) 选择一个该处理程序使用的 Formatter 对象。
  • [addFilter()](<https://docs.python.org/zh-cn/3.8/library/logging.html#logging.Handler.addFilter>) 和 [removeFilter()](<https://docs.python.org/zh-cn/3.8/library/logging.html#logging.Handler.removeFilter>) 分别在处理程序上配置和取消配置过滤器对象。

Formatter 格式化程序

Formatter对象配置日志最终顺序、结构和内容。可以实例化Handler类,如果需要特殊行为,可能需要继承Handler类。构造函数有三个可选参数:—— 消息格式字符串、日期格式字符串和样式指示符。

logging.Formatter.__init__(fmt=None, datefmt=None, style='%')

如果没有消息格式字符串,则默认使用原始消息。如果没有日期格式字符串,则默认日期格式为:

%Y-%m-%d %H:%M:%S

最后加上毫秒数。 style,'{ ' 或 '$' 之一。 如果未指定其中一个,则将使用 ''。

如果 style 是 '%',则消息格式字符串使用 %(<dictionary key>)s 样式字符串替换;可能的键值在 LogRecord 属性 中。 如果样式为 '{',则假定消息格式字符串与 str.format() (使用关键字参数)兼容,而如果样式为 '$' ,则消息格式字符串应符合 string.Template.substitute()

以下消息格式字符串将以人类可读的格式记录时间、消息的严重性以及消息的内容,按此顺序:

'%(asctime)s - %(levelname)s - %(message)s'

格式化程序使用用户可配置的函数将记录的创建时间转换为元组。 默认情况下,使用 time.localtime() ;要为特定格式化程序实例更改此项,请将实例的 converter 属性设置为具有相同签名的函数 time.localtime() 或 time.gmtime() 。 要为所有格式化程序更改它,例如,如果你希望所有记录时间都以 GMT 显示,请在格式化程序类中设置 converter 属性(对于 GMT 显示,设置为 time.gmtime )。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值