15.7. 日志记录-Python 的日志记录工具

Important

此页面包含 API 参考信息。有关教程信息和更多高级主题的讨论,请参见

源代码: Lib/logging/init.py


2.3 版的新Function。

该模块定义函数和类,这些函数和类为应用程序和库实现了灵活的事件日志记录系统。

由标准库模块提供的日志记录 API 的主要好处是所有 Python 模块都可以参与日志记录,因此您的应用程序日志可以包括您自己的消息以及与第三方模块的消息集成的消息。

该模块提供了很多Function和灵 Active。如果您不熟悉日志记录,那么最好的方法是查看教程(请参阅右侧的链接)。

下面列出了模块定义的基本类及其Function。

15.7.1. Logger 对象

Logger 具有以下属性和方法。请注意,永远不会直接实例化 Logger,而是始终pass模块级函数logging.getLogger(name)实例化。对具有相同名称的getLogger()的多次调用将始终返回对同一 Logger 对象的引用。

name可能是句点分隔的分层值,例如foo.bar.baz(尽管例如也可以是普通foo)。层次结构列表中位于最下方的 Logger 是列表中较高位置的 Logger 的子级。例如,给定名称为foo的 Logger,名称为foo.barfoo.bar.bazfoo.bam的 Logger 都是foo的后代。记录程序名称层次结构类似于 Python 包层次结构,如果您使用推荐的结构logging.getLogger(__name__)在每个模块的基础上组织记录程序,则该记录程序名称层次结构也相同。这是因为在模块中,__name__是 Python 包命名空间中模块的名称。

如果此结果为 false,则不会将日志记录消息传递给祖先 Logger 的处理程序。

构造函数将此属性设置为True

Note

如果将处理程序附加到 Logger及其一个或多个祖先,它可能会多次发出相同的记录。通常,您不需要将一个处理程序附加到一个以上的 Logger 上-如果仅将它附加到 Logger 层次结构中最高的适当 Logger 上,则它将看到所有后代 Logger 记录的所有事件,前提是它们的传播设置保留为True。一种常见的情况是仅将处理程序附加到根 Logger,并让传播来处理其余部分。

术语“委托给父代”是指如果 Logger 具有 NOTSET 级别,则遍历其祖先 Logger 链,直到找到非 NOTSET 级别的祖先或到达根为止。

如果发现某个祖先的级别不是 NOTSET,那么该祖先的级别将被视为祖先搜索开始的 Logger 的有效级别,并用于确定如何处理日志事件。

如果到达根目录,并且其级别为 NOTSET,则将处理所有消息。否则,将使用根的级别作为有效级别。

有关级别列表,请参见Logging Levels

2.7 版的新Function。

在* kwargs 中有两个关键字参数被检查: exc_info *,如果不将其评估为 false,则会导致将异常信息添加到日志消息中。如果提供了一个异常 Tuples(由sys.exc_info()返回的格式),则使用它;否则,将使用它。否则,将调用sys.exc_info()以获取异常信息。

第二个关键字参数是* extra *,可用于传递字典,该字典用于使用用户定义的属性填充为记录事件创建的 LogRecord 的__dict__。然后可以根据需要使用这些自定义属性。例如,可以将它们合并到已记录的消息中。例如:

FORMAT = '%(asctime)-15s %(clientip)s %(user)-8s %(message)s'
logging.basicConfig(format=FORMAT)
d = {'clientip': '192.168.0.1', 'user': 'fbloggs'}
logger = logging.getLogger('tcpserver')
logger.warning('Protocol problem: %s', 'connection reset', extra=d)

将打印类似

2006-02-08 22:20:02,165 192.168.0.1 fbloggs  Protocol problem: connection reset

如果选择在已记录的消息中使用这些属性,则需要格外小心。例如,在上面的示例中,Formatter已设置为格式字符串,该字符串在 LogRecord 的属性字典中期望为“ clientip”和“ user”。如果缺少这些内容,则将不会记录该消息,因为会发生字符串格式化异常。因此,在这种情况下,您始终需要pass这些键传递* extra *词典。

尽管这可能很烦人,但是此Function旨在用于特殊情况,例如在多个上下文中执行相同代码的多线程服务器,并且出现的有趣条件取决于此上下文(例如,远程 Client 端 IP 地址和已验证用户名,在上面的示例中)。在这种情况下,很可能将专门的Formatter与特定的Handler一起使用。

在版本 2.4 中更改:添加了函数名称。在早期版本中,文件名和行号以 2 元素 Tuples 的形式返回。

在版本 2.5 中更改:添加了* func extra *。

15.7.2. 记录级别

下表中给出了日志记录级别的数值。如果您想定义自己的级别,并且需要它们具有相对于 sched 义级别的特定值,那么这些是最重要的。如果用相同的数值定义一个级别,它将覆盖 sched 义的值;sched 义名称丢失。

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

15.7.3. 处理程序对象

处理程序具有以下属性和方法。注意Handler永远不会直接实例化;此类充当更有用的子类的基础。但是,子类中的init()方法需要调用Handler.init()

有关级别列表,请参见Logging Levels

有关标准随附的处理程序的列表,请参见logging.handlers

15.7.4. 格式化对象

Formatter对象具有以下属性和方法。它们负责将LogRecord转换为(通常)可由人或外部系统解释的字符串。基本Formatter允许指定格式字符串。如果未提供任何参数,则使用默认值'%(message)s',它仅将消息包括在日志记录调用中。要在格式化输出中有其他信息项(例如时间戳记),请 continue 阅读。

格式化程序可以使用格式化字符串初始化,该字符串利用LogRecord属性的知识-例如上述默认值,它利用用户的消息和参数已预先格式化为LogRecord的* message *属性的事实。此格式字符串包含标准的 Python%样式 Map 键。有关字符串格式的更多信息,请参见字符串格式化操作部分。

LogRecord中有用的 Map 键在LogRecord attributes的部分中给出。

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

15.7.5. 筛选对象

HandlersLoggers可以使用Filters进行比级别所提供的更为复杂的过滤。基本过滤器类仅允许 Logger 层次结构中特定点以下的事件。例如,使用“ AB”初始化的过滤器将允许 Logger“ A.B”,“ ABC”,“ ABCD”,“ ABD”等记录事件,但不允许“ A.BB”,“ BAB”等记录。如果使用空字符串初始化,则会传递所有事件。

请注意,在处理程序发出事件之前,将先查询附加到处理程序的过滤器,而在将事件发送到处理程序之前,无论何时记录事件(使用debug()info()等),都将查询附加到 Logger 的过滤器。这意味着由后代 Logger 生成的事件将不会被 Logger 的过滤器设置过滤,除非该过滤器也已应用于这些后代 Logger。

实际上,您不需要继承Filter:可以传递具有filter方法且具有相同语义的任何实例。

尽管过滤器主要用于根据比级别更复杂的条件来过滤记录,但是它们可以查看由其附加到的处理程序或 Logger 处理的每条记录:如果您要进行计数等操作,这将非常有用记录由特定的 Logger 或处理程序处理,或在要处理的 LogRecord 中添加,更改或删除属性。显然,更改 LogRecord 时需要格外小心,但确实允许将上下文信息注入日志中(请参阅使用过滤器传递上下文信息)。

15.7.6. LogRecord 对象

LogRecord实例会在每次记录内容时由Logger自动创建,并且可以passmakeLogRecord()手动创建(例如,pass网络接收的腌制事件)。

主要信息在msgargs中传递,它们使用msg % args组合在一起以创建记录的message字段。

在版本 2.5 中更改:添加了* func *。

15.7.7. LogRecord 属性

LogRecord 具有许多属性,其中大多数是从构造函数的参数派生的。 (请注意,名称在 LogRecord 构造函数参数和 LogRecord 属性之间并不总是完全对应.)这些属性可用于将 Logging 的数据合并到格式字符串中。下表(按字母 Sequences)以%样式格式字符串列出了属性名称,它们的含义和相应的占位符。

Attribute name Format Description
args 您不需要自己格式化。 参数的 Tuples 合并到msg以产生message,或者是将其值用于合并的 dict(当只有一个参数且它是一本字典时)。
asctime %(asctime)s LogRecord创建时的可读时间。默认情况下,其格式为“ 2003-07-08 16:49:45,896”(逗号后的数字是时间的毫秒部分)。
created %(created)f 创建LogRecord的时间(由time.time()返回)。
exc_info 您不需要自己格式化。 异常 Tuples(la sys.exc_info),或者,如果没有发生异常,则None
filename %(filename)s pathname的文件名部分。
funcName %(funcName)s 包含日志记录调用的函数的名称。
levelname %(levelname)s 消息的文本记录级别('DEBUG''INFO''WARNING''ERROR''CRITICAL')。
levelno %(levelno)s 消息的数字记录级别(DEBUGINFOWARNINGERRORCRITICAL)。
lineno %(lineno)d 发出日志记录调用的源行号(如果有)。
module %(module)s 模块(filename的名称部分)。
msecs %(msecs)d 创建LogRecord的时间的毫秒部分。
message %(message)s 记录的消息,计算为msg % args。调用Formatter.format()时设置。
msg 您不需要自己格式化。 原始日志记录调用中传递的格式字符串。与args合并以产生message或任意对象(请参见使用任意对象作为消息)。
name %(name)s 用于记录呼叫的 Logger 的名称。
pathname %(pathname)s 发出日志记录调用的源文件的完整路径名(如果有)。
process %(process)d 进程 ID(如果有)。
processName %(processName)s 进程名称(如果有)。
relativeCreated %(relativeCreated)d 创建 LogRecord 的时间(以毫秒为单位),相对于加载日志模块的时间。
thread %(thread)d 线程 ID(如果有)。
threadName %(threadName)s 线程名称(如果有)。

在版本 2.5 中更改:添加了* funcName *。

在 2.6 版中进行了更改:添加了* processName *。

15.7.8. LoggerAdapter 对象

LoggerAdapter实例用于将上下文信息方便地传递到日志记录调用中。有关用法示例,请参见将上下文信息添加到日志输出部分。

2.6 版的新Function。

除此之外,LoggerAdapter还支持Logger的以下方法:debug()info()warning()error()exception()critical()log()isEnabledFor()。这些方法与Logger中的方法具有相同的签名,因此对于这些调用,可以将两种类型的实例互换使用。

在 2.7 版中进行了更改:isEnabledFor()方法已添加到LoggerAdapter。此方法委托给基础 Logger。

15.7.9. 线程安全

日志记录模块旨在实现线程安全,而 Client 端无需执行任何特殊工作。它pass使用线程锁来实现。有一个锁用于序列化对模块共享数据的访问,每个处理程序还创建一个锁,以序列化对对其基础 I/O 的访问。

如果要使用signal模块实现异步 signal 处理程序,则可能无法使用此类处理程序中的日志记录。这是因为threading模块中的锁实现并不总是可重入的,因此不能从此类 signal 处理程序中调用。

15.7.10. 模块级Function

除了上述类之外,还有许多模块级Function。

使用给定名称对该函数的所有调用均返回相同的 Logger 实例。这意味着 Logger 实例永远不需要在应用程序的不同部分之间传递。

class MyLogger(logging.getLoggerClass()):
    # ... override behaviour here

在* kwargs 中有两个关键字参数被检查: exc_info *,如果不将其评估为 false,则会导致将异常信息添加到日志消息中。如果提供了一个异常 Tuples(由sys.exc_info()返回的格式),则使用它;否则,将使用它。否则,将调用sys.exc_info()以获取异常信息。

另一个可选的关键字参数是* extra *,它可以用于传递字典,该字典用于使用用户定义的属性填充为记录事件创建的 LogRecord 的__dict__。然后可以根据需要使用这些自定义属性。例如,可以将它们合并到已记录的消息中。例如:

FORMAT = "%(asctime)-15s %(clientip)s %(user)-8s %(message)s"
logging.basicConfig(format=FORMAT)
d = {'clientip': '192.168.0.1', 'user': 'fbloggs'}
logging.warning("Protocol problem: %s", "connection reset", extra=d)

将打印如下内容:

2006-02-08 22:20:02,165 192.168.0.1 fbloggs  Protocol problem: connection reset

如果选择在已记录的消息中使用这些属性,则需要格外小心。例如,在上面的示例中,Formatter已设置为格式字符串,该字符串在 LogRecord 的属性字典中期望为“ clientip”和“ user”。如果缺少这些内容,则将不会记录该消息,因为会发生字符串格式化异常。因此,在这种情况下,您始终需要pass这些键传递* extra *词典。

尽管这可能很烦人,但是此Function旨在用于特殊情况,例如在多个上下文中执行相同代码的多线程服务器,并且出现的有趣条件取决于此上下文(例如,远程 Client 端 IP 地址和已验证用户名,在上面的示例中)。在这种情况下,很可能将专门的Formatter与特定的Handler一起使用。

在版本 2.5 中更改:添加了额外

Note

上面委派给 rootLogger 的模块级别的便捷Function调用basicConfig()以确保至少有一个处理程序可用。因此,除非在启动线程之前(至少)在根 Logger 中添加了至少一个处理程序,否则它们不应在 2.7.1 和 3.2 之前的 Python 版本中用于线程中。在早期版本的 Python 中,由于basicConfig()中的线程安全性不足,这可能(在极少数情况下)导致将处理程序多次添加到 rootLogger 中,这反过来又可能导致同一事件的多个消息。

Note

如果您想定义自己的级别,请参阅Custom Levels的部分。

Note

例如,在在Logger实例和处理程序上设置级别。此函数用于pass%(levelname)s格式说明符(请参阅LogRecord attributes)在整数级别和格式化日志输出中显示的级别名称之间进行转换。

如果根 Logger 已经为其配置了处理程序,则此Function不执行任何操作。

在版本 2.4 中更改:以前,basicConfig()没有任何关键字参数。

Note

在启动其他线程之前,应从主线程调用此函数。在 2.7.1 和 3.2 之前的 Python 版本中,如果从多个线程调用此函数,则有可能(在极少数情况下)多次将处理程序添加到根 Logger 中,从而导致意外结果,例如消息在日志中被复制。

支持以下关键字参数。

Format Description
filename 指定使用指定的文件名而不是 StreamHandler 创建 FileHandler。
filemode 如果指定了* filename *,则以此模式打开文件。默认为'a'
format 为处理程序使用指定的格式字符串。
datefmt 使用time.strftime()接受的指定日期/时间格式。
level 将根记录程序级别设置为指定的level
stream 使用指定的流初始化 StreamHandler。请注意,此参数与* filename 不兼容-如果两者都存在,则 stream *将被忽略。

15.7.11. 与警告模块集成

captureWarnings()函数可用于将loggingwarnings模块集成。

如果* capture *为True,则由warnings模块发出的警告将重定向到日志记录系统。具体来说,将使用warnings.formatwarning()格式化警告,并将结果字符串记录到名为'py.warnings'的严重性为WARNING的 Logger 中。

如果* capture *为False,则将停止将警告重定向到日志记录系统,并且将警告重定向到其原始目的地(即,在调用captureWarnings(True)之前生效的警告)。

See also

  • Module logging.config

  • 日志记录模块的配置 API。

  • Module logging.handlers

  • 日志记录模块随附的有用处理程序。

  • PEP 282-记录系统

  • 将该特性描述为包含在 Python 标准库中的提案。

  • 原始 Python 记录程序包

  • 这是logging软件包的原始来源。该站点提供的软件包版本适用于 Python 1.5.2、2.1.x 和 2.2.x,它们在标准库中不包含logging软件包。

首页