日志基础

参考:https://docs.python.org/3/howto/logging.html

4 个核心组件

组件 说明
logger 程序用来记录日志
handler 将日志发送到合适的目的地
filter 决定哪些日志被输出
formatter 日志以何种格式输出

logger

常用配置方法

  • Logger.getLever() 要处理的最低级别消息(内置级别中,debug 是最低级而 critical 是最高级)
  • Logger.addHandler()Logger.removeHandler() 添加或移除 handler 对象
  • Logger.addFilter()Logger.removeFilter() 添加或移除 filter 对象

无需在每个 logger 上调用这些配置方法

  • logger 有个 生效级别 的概念。如果一个 logger 未明确设定级别,则会继承其父 logger 的级别;若父 logger 也没有设定级别,会继续查找更上层的 logger 的级别,直到 root looger。root logger 默认的级别是 WARNING
  • handler 同理,只需要设定最顶级的 logger 的 handler 即可

创建日志

  • Logger.debug() Logger.info() Logger.warning() Logger.error() Logger.critical() 不解释
  • Logger.exception()Logger.error() 相似,不同之处在于 Logger.exception() 输出异常堆栈,注意:仅在异常处理时调用此方法
  • Logger.log() 该方法要指定一个明确的日志级别,可用于自定义的的日志级别

getLogger()

通过 logger 名字反映包/模块层次及事件在哪发生。

logger = logging.getLogger(__name__)
  • 如果不指定名字,则为 root
  • 用相同的名字多次调用该方法返回的是同一个日志对象
  • 如果 foo 是一个 logger 的名字,那么 foo.bar foo.bar.baz foo.bam 都是 foo 的后代

handler

handler,把日志发送到关联的目的地的东东。logger.addHandler(),可以添加 0 个或多个 handler

  • 可以把日志记录到文件,http GET/POST,email,队列,或操作系统特定的日志机制,诸如 syslog 或 windows NT 事务日志。通过 handler 类来设定目的地
  • 可以创建自己的 handler
  • 默认情况下,没有设定目的地。
  • 可以用 basicConfig() 指定,诸如 console(控制台) 或 file(文件)。调用 info()debug() 等方法时,会自动检测有无设定目的地,如果没有设置,会将 console(控制台) 设置为目的地。

例如把所有日志发送到一个文件,高于 error 的日志发送到标准输出,cirtical 发送邮件

常用的方法

  • setLevel() 和 logger 的一样,指定一个最低级别。为什么要有 2 个 setLevel()
    • logger.setLevel() 判断哪个级别的消息要发送到 handler
    • handler.setLevel() 判断哪个消息将发送
  • setFormatter() 为 handler 选择一个 formatter
  • addFilter() removeFilter() 设定 handler 的 filter

应用程序代码不应直接实例化和使用 Handler。相反,Handler 是一个基类,它定义了所有 handler 应该具有的接口,并建立了一些子类可以使用(或重写)的默认行为

内置的 handler

python 内置了 Hanlder 的一些子类,参考:https://docs.python.org/3/howto/logging.html#useful-handlers

  • StreamHandler 发送消息到 stream (类文件对象) 可以理解为就是 控制台(console)
  • FileHandler 发送消息到磁盘文件
  • BaseRotatingHandler 这是 轮换日志 处理器的基类,不要直接用这个handler,用它的子类
    • RotatingFileHandler 发送消息到磁盘文件,可以设定文件按最大尺寸进行轮换
    • TimedRotatingFileHandler 发送消息到磁盘文件,并按时间轮换文件
  • SocketHandler 发送消息到 TCP/IP sockets
  • DatagramHandler 发送消息到 UDP sockets
  • SMTPHandler 发送消息到 email 地址
  • SysLogHandler 可以远程发送日志到 unix 的 syslog 守护进程
  • NTEventLogHandler 发送消息到 Windows NT/2000/XP 事务日志
  • MemoryHandler 发送日志到内存缓冲区,该缓冲区有其持久化到磁盘的策略
  • HTTPHandler 用 GET/POST 方法发送消息到一个 HTTP 服务器
  • WatchedFileHandler 仅用于类 unix 系统,会观察日志文件,如果日志文件发生改变,会关闭并用文件名重新打开文件
  • QueueHandler 发送消息到队列,例如一些多进程模块
  • NullHandler 不处理错误日志。库开发者可以用给这个 handler,这样可以避免库的使用者未配置 logging 时出现的 "No handlers could be found for logger XXX" 消息

注意

NullHandler, StreamHandler and FileHandler 在 logging 包,其他子类在 logging.handlers 包

formatter

basicConfig() 默认格式如下

severity:logger name:message

不同于 Handler,可以直接实例化 Formatter 对象,构造器接收 3 个可选参数:消息格式,时间格式,样式

logging.Formatter.__init__(fmt=None, datefmt=None, style='%')
  • 消息格式 如果未设定,使用原始的消息
  • 时间格式 如果未设定,则为 %Y-%m-%d %H:%M:%S
  • 样式 %{$ 之一,若未设定则为 % (应该是设定一个指示变量的占位符)

下面的消息格式串将按顺序记录时间、日志级别、消息内容

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

要设定格式,参考 Formatter Objects

formatter 用一个用户设定的函数来将日志创建时间转换为 tuple。默认情况下使用 time.localtime(),若要改变,设定 formatter 的 converter 属性为一个和 time.localtime()time.gmttime() 参数相同的函数,如果要修改所有 formatter 的 converter 属性,则改变 Formatterconverter 属性

配置 logging

有 3 种配置方法

  1. 在 python 代码里创建 logger, handler 和 formatter 并调用上述的配置方法
  2. 创建一个配置文件,使用 fileConfig() 方法来加载,配置文件格式见 file format
  3. 创建一个配置 dict 发送给 dictConfig() 方法

对于 2,3 参考 配置函数

配置示例

用代码配置

import logging

# create logger
logger = logging.getLogger('simple_example')
logger.setLevel(logging.DEBUG)

# create console handler and set level to debug
ch = logging.StreamHandler()
ch.setLevel(logging.DEBUG)

# create formatter
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')

# add formatter to ch
ch.setFormatter(formatter)

# add ch to logger
logger.addHandler(ch)

# 'application' code
logger.debug('debug message')
logger.info('info message')
logger.warn('warn message')
logger.error('error message')
logger.critical('critical message')

在命令行运行并输出

$ python simple_logging_module.py
2005-03-19 15:10:26,618 - simple_example - DEBUG - debug message
2005-03-19 15:10:26,620 - simple_example - INFO - info message
2005-03-19 15:10:26,695 - simple_example - WARNING - warn message
2005-03-19 15:10:26,697 - simple_example - ERROR - error message
2005-03-19 15:10:26,773 - simple_example - CRITICAL - critical message

用配置文件

配置文件 logging.conf

[loggers]
keys=root,simpleExample

[handlers]
keys=consoleHandler

[formatters]
keys=simpleFormatter

[logger_root]
level=DEBUG
handlers=consoleHandler

[logger_simpleExample]
level=DEBUG
handlers=consoleHandler
qualname=simpleExample
propagate=0

[handler_consoleHandler]
class=StreamHandler
level=DEBUG
formatter=simpleFormatter
args=(sys.stdout,)

[formatter_simpleFormatter]
format=%(asctime)s - %(name)s - %(levelname)s - %(message)s
datefmt=

代码

import logging
import logging.config

logging.config.fileConfig('logging.conf')

# create logger
logger = logging.getLogger('simpleExample')

# 'application' code
logger.debug('debug message')
logger.info('info message')
logger.warn('warn message')
logger.error('error message')
logger.critical('critical message')

命令行运行并输出

$ python simple_logging_config.py
2005-03-19 15:38:55,977 - simpleExample - DEBUG - debug message
2005-03-19 15:38:55,979 - simpleExample - INFO - info message
2005-03-19 15:38:56,054 - simpleExample - WARNING - warn message
2005-03-19 15:38:56,055 - simpleExample - ERROR - error message
2005-03-19 15:38:56,130 - simpleExample - CRITICAL - critical message

results matching ""

    No results matching ""