Python 的 logging 日志模块用于追踪和记录程序运行时发生的事件。

一个超级简单的例子:

import logging
# logging.basicConfig(filename='out.log',level=30)  # 输出日志到文件
logging.warning('一条警告消息')  # 打印日志到屏幕
logging.info('啦啦啦')  # 默认日志级别是warning,所以这条不会显示

输出:

WARNING:root:一条警告消息

Logging 采用模块化方法,并提供了以下几类组件:

  • Logger - 提供了可直接使用的日志接口。
  • Handler - 日志的处理方式,比如说是打印到屏幕还是记录到文件,或是发送到日志服务器。
  • Filter - 提供更精细的方式确定哪些日志记录需要输出。
  • Formatter - 指定日志记录的输出格式。

通过调用 Logger 类的实例来执行日志记录。每个实例都有一个名称,它们在概念上以一个命名空间层次结构排列,使用点(.)作为分隔符。默认是root

logger = logging.getLogger('a.b.c')

日志级别

日志记录级别和数值如下,可自定义级别和数值,相同会覆盖预定义。

Level Value
CRITICAL 50
ERROR 40
WARNING 30
INFO 20
DEBUG 10
NOTSET 0

Logger

Logger 对象有三重工作。首先,程序调用Logger对象,以便应用程序可以在运行时记录消息。第二,Logger对象根据 Filter 对象和 formater 对象过滤确定要执行的日志消息。第三,Logger 对象将相关日志消息传递给所有相关 Handler。

Logger 对象中使用最广泛的方法分为两类:配置和消息发送。

这些是最常用的配置方法:

Logger.setLevel() 指定将处理的最低严重性级别的日志消息,其中 debug 是最低内置严重性级别, critical 是最高的内置严重性。例如,如果严重性级别为INFO,则 Logger 将仅处理INFO,WARNING,ERROR 和 CRITICAL 消息,并将忽略DEBUG消息。

Logger.addHandler()Logger.removeHandler() 从 Logger 对象中添加和删除 Handler对象。

Logger.addFilter()Logger.removeFilter() 从 Logger 对象中添加和删除 Filter 对象。

配置 Logger 对象后,以下方法创建日志消息:

Logger.debug()Logger.info()Logger.warning()Logger.error(),和Logger.critical()用于创建对应级别的日志记录。该消息实际上是一个格式串,其可以包含的标准字符串替换语法%s%d%f,等。其余的参数是与消息中的替换字段对应的对象列表。

Logger.exception() 创建类似于Logger.error()的日志消息。仅从异常处理程序调用此方法。

Logger.log() 将日志级别作为显式参数。

getLogger() 如果提供了指定的名称,则返回对具有指定名称的 Logger 实例的引用,否则返回root

Handler

Handler 对象负责将适当的日志消息(基于日志级别)分派到指定目的地。可使用addHandler()方法向其自身添加零个或多个Handler对象。

常用配置方法:

setLevel()设置输出到指定Handler的日志级别。 setFormatter()设置日志格式。 addFilter()removeFilter()

Handler种类

  • StreamHandler
  • FileHandler
  • NullHandler
  • WatchedFileHandler
  • BaseRotatingHandler
  • RotatingFileHandler
  • TimedRotatingFileHandler
  • SocketHandler
  • DatagramHandler
  • SysLogHandler
  • NTEventLogHandler
  • SMTPHandler
  • MemoryHandler
  • HTTPHandler
  • QueueHandler

感兴趣可以查看更详细信息

Formater

用于格式化日志输出。

例如:

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

所有内置属性

属性名称 格式 说明
asctime %(asctime)s 时间
created %(created)f 日志创建时间戳
filename %(filename)s 文件名称
funcName %(funcName)s 函数名称
levelname %(levelname)s 级别
levelno %(levelno)s 级别(值)
lineno %(lineno)d 所在行
module %(module)s 模块名称
msecs %(msecs)d 毫秒部分
message %(message)s 日志消息
name %(name)s 日志名称
pathname %(pathname)s 路径
process %(process)d 进程ID
processName %(processName)s 进程名称
relativeCreated %(relativeCreated)d 日志创建毫秒数
thread %(thread)d 线程ID
threadName %(threadName)s 线程名称

简单的例子

import logging

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

# create file handler which logs even debug messages
fh = logging.FileHandler('spam.log')
fh.setLevel(logging.DEBUG)

# create console handler with a higher log level
ch = logging.StreamHandler()
ch.setLevel(logging.ERROR)

# create formatter and add it to the handlers
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
ch.setFormatter(formatter)
fh.setFormatter(formatter)

# add the handlers to logger
logger.addHandler(ch)
logger.addHandler(fh)

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

输出:

2017-07-03 15:21:34,586 - simple_example - ERROR - error message
2017-07-03 15:21:34,587 - simple_example - CRITICAL - critical message

稍微复杂的例子

import logging
import auxiliary_module

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

# create file handler which logs even debug messages
fh = logging.FileHandler('spam.log')
fh.setLevel(logging.DEBUG)

# create console handler with a higher log level
ch = logging.StreamHandler()
ch.setLevel(logging.ERROR)

# create formatter and add it to the handlers
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
fh.setFormatter(formatter)
ch.setFormatter(formatter)

# add the handlers to the logger
logger.addHandler(fh)
logger.addHandler(ch)

logger.info('creating an instance of auxiliary_module.Auxiliary')
a = auxiliary_module.Auxiliary()
logger.info('created an instance of auxiliary_module.Auxiliary')

logger.info('calling auxiliary_module.Auxiliary.do_something')
a.do_something()
logger.info('finished auxiliary_module.Auxiliary.do_something')

logger.info('calling auxiliary_module.some_function()')
auxiliary_module.some_function()
logger.info('done with auxiliary_module.some_function()')

auxiliary_module文件:

import logging

# create logger
module_logger = logging.getLogger('spam_application.auxiliary')


class Auxiliary:
    def __init__(self):
        self.logger = logging.getLogger('spam_application.auxiliary.Auxiliary')
        self.logger.info('creating an instance of Auxiliary')

    def do_something(self):
        self.logger.info('doing something')
        a = 1 + 1
        self.logger.info('done doing something')


def some_function():
    module_logger.info('received a call to "some_function"')

spam.log的内容:

2017-07-03 15:28:41,109 - spam_application - INFO - creating an instance of auxiliary_module.Auxiliary
2017-07-03 15:28:41,109 - spam_application.auxiliary.Auxiliary - INFO - creating an instance of Auxiliary
2017-07-03 15:28:41,109 - spam_application - INFO - created an instance of auxiliary_module.Auxiliary
2017-07-03 15:28:41,109 - spam_application - INFO - calling auxiliary_module.Auxiliary.do_something
2017-07-03 15:28:41,110 - spam_application.auxiliary.Auxiliary - INFO - doing something
2017-07-03 15:28:41,110 - spam_application.auxiliary.Auxiliary - INFO - done doing something
2017-07-03 15:28:41,110 - spam_application - INFO - finished auxiliary_module.Auxiliary.do_something
2017-07-03 15:28:41,110 - spam_application - INFO - calling auxiliary_module.some_function()
2017-07-03 15:28:41,110 - spam_application.auxiliary - INFO - received a call to "some_function"
2017-07-03 15:28:41,110 - spam_application - INFO - done with auxiliary_module.some_function()

参考

https://docs.python.org/3/howto/logging.html
https://docs.python.org/3/library/logging.html
https://docs.python.org/3.6/howto/logging-cookbook.html