日志记录#

logging 模块提供功能齐全且灵活的日志记录系统。在最简单的情况下,日志消息被发送到文件或 sys.stderr

import logging
# 示例
logging.debug('Debugging information')
logging.info('Informational message')
logging.warning('Warning:config file %s not found', 'server.conf')
logging.error('Error occurred')
logging.critical('Critical error -- shutting down')
WARNING:root:Warning:config file server.conf not found
ERROR:root:Error occurred
CRITICAL:root:Critical error -- shutting down

默认情况下,informational 和 debugging 消息被压制,输出会发送到标准错误流。其他输出选项包括将消息转发到电子邮件,数据报,套接字或 HTTP 服务器。新的过滤器可以根据消息优先级选择不同的路由方式:DEBUGINFOWARNINGERRORCRITICAL

level 指定了日志的级别,这样,便可以显示 DEBUG 信息:

import logging
logging.basicConfig(level=logging.DEBUG)

logging.debug('Debugging information')

日志系统可以直接从 Python 配置,也可以从用户配置文件加载,以便自定义日志记录而无需更改应用程序。

可以将日志写入文件:

import logging
logging.basicConfig(filename='example.log', level=logging.DEBUG)

basicConfig() 的调用应该在 debug()info() 等的前面。因为它被设计为一次性的配置,只有第一次调用会进行操作,随后的调用不会产生有效操作。

如果多次运行 basicConfig() 脚本,则连续运行的消息将追加到文件 example.log。 如果你希望每次运行重新开始,而不是记住先前运行的消息,则可以通过将上例中的调用更改为来指定 filemode 参数:

import logging
logging.basicConfig(filename='example.log',
                    filemode='w',
                    level=logging.DEBUG)

输出将与之前相同,但不再追加进日志文件,因此早期运行的消息将丢失。

常用设置#

logging.LogRecord 可以定制日志显示格式。

更改显示消息的格式#

要更改用于显示消息的格式,你需要指定要使用的格式:

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')
WARNING:root:And this, too

在消息中显示日期/时间#

要显示事件的日期和时间,你可以在格式字符串中放置 '%(asctime)s'

import logging

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

控制日期/时间的格式,请为 basicConfig() 提供 datefmt 参数,如下例所示:

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.')
WARNING:root:is when this event was logged.

进阶日志教程#

日志库采用模块化方法,并提供几类组件:记录器、处理器、过滤器和格式器。

  • 记录器 (Logger) 暴露了应用程序代码直接使用的接口。

  • 处理器 (Handler) 将日志记录(由记录器创建)发送到适当的目标。

  • 过滤器 (Filter) 提供了更细粒度的功能,用于确定要输出的日志记录。

  • 格式器 (Formatter) 指定最终输出中日志记录的样式。

日志事件信息在 LogRecord 实例中的记录器、处理器、过滤器和格式器之间传递。

小技巧

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

logger = logging.getLogger(__name__)

这意味着记录器名称跟踪包或模块的层次结构,并且直观地从记录器名称显示记录事件的位置。

多个 handler 和多种 formatter#

下面的示例实现终端和文件日志的不同管理:

import logging

# 创建文件处理程序,并记录调试消息
fh = logging.FileHandler("debug.log")
fh.setLevel(logging.DEBUG)
# 创建日志级别更高的控制台处理程序
ch = logging.StreamHandler()
ch.setLevel(logging.INFO) # 或者logging.ERROR
# 创建formatter并将其
fh_formatter = logging.Formatter("%(levelname)s|%(asctime)s|%(name)s| -> %(message)s|%(module)s.%(funcName)s@%(pathname)s")
ch_formatter = logging.Formatter("%(levelname)s|%(asctime)s -> %(message)s")
fh.setFormatter(fh_formatter)
ch.setFormatter(ch_formatter)
logging.basicConfig(
    level=logging.DEBUG,
    handlers=[fh, ch]
)