16.6. logging — Python 的日志记录工具 — Python 文档

来自菜鸟教程
Python/docs/3.6/library/logging
跳转至:导航、​搜索

16.6. 日志记录 — Python 的日志记录工具

源代码: :source:`Lib/logging/__init__.py`

重要的

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



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

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

该模块提供了许多功能和灵活性。 如果您不熟悉日志记录,掌握它的最佳方法是查看教程(请参见右侧的链接)。

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

  • 记录器公开应用程序代码直接使用的接口。
  • 处理程序将日志记录(由记录器创建)发送到适当的目的地。
  • 过滤器提供了一种更细粒度的设施,用于确定要输出哪些日志记录。
  • 格式化程序指定最终输出中日志记录的布局。

16.6.1. 记录器对象

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

name 可能是一个以句点分隔的分层值,例如 foo.bar.baz(尽管它也可能只是普通的 foo,例如)。 在层次列表中更靠后的记录器是列表中更高的记录器的孩子。 例如,给定一个名称为 foo 的记录器,名称为 foo.barfoo.bar.bazfoo.bam 的记录器都是 [ X139X]。 记录器名称层次结构类似于 Python 包层次结构,如果您使用推荐的结构 logging.getLogger(__name__) 在每个模块的基础上组织记录器,则与它相同。 这是因为在模块中,__name__ 是 Python 包命名空间中的模块名称。

class logging.Logger
propagate

如果此属性评估为 true,则除了附加到此记录器的任何处理程序之外,记录到此记录器的事件将传递给更高级别(祖先)记录器的处理程序。 消息直接传递给祖先记录器的处理程序——既不考虑所讨论的祖先记录器的级别或过滤器。

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

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

笔记

如果您将处理程序附加到记录器 的一个或多个祖先,它可能会多次发出相同的记录。 通常,您不需要将处理程序附加到多个记录器 - 如果您只是将它附加到记录器层次结构中最高的适当记录器,那么它将看到所有后代记录器记录的所有事件,前提是它们传播设置保留为 True。 一个常见的场景是只将处理程序附加到根记录器,让传播处理其余的事情。

setLevel(level)

将此记录器的阈值设置为 级别 。 比 级别 严重的日志消息将被忽略; 严重性为 level 或更高的日志消息将由任何一个或多个处理程序发送此记录器,除非处理程序的级别已设置为比 级别 更高的严重级别。

创建记录器时,级别设置为 NOTSET(当记录器是根记录器时,这会导致处理所有消息,或者当记录器是非根记录器时将其委托给父级)。 请注意,根记录器是使用级别 WARNING 创建的。

术语“委托给父级”意味着如果记录器的级别为 NOTSET,则遍历其祖先记录器链,直到找到级别不是 NOTSET 的祖先,或者到达根。

如果发现祖先的级别不是 NOTSET,则该祖先的级别被视为祖先搜索开始的记录器的有效级别,并用于确定如何处理日志记录事件。

如果到达根,并且它具有 NOTSET 级别,则将处理所有消息。 否则,根的级别将用作有效级别。

有关级别列表,请参阅 日志级别

3.2 版更改: level 参数现在接受级别的字符串表示形式,例如“INFO”,作为整数常量(例如 INFO)的替代。 但是请注意,级别在内部存储为整数,而方法例如 getEffectiveLevel()isEnabledFor() 将返回/期望传递整数。

isEnabledFor(lvl)

指示此记录器是否会处理严重性为 lvl 的消息。 此方法首先检查由 logging.disable(lvl) 设置的模块级级别,然后检查由 getEffectiveLevel() 确定的记录器的有效级别。

getEffectiveLevel()

指示此记录器的有效级别。 如果使用 setLevel() 设置了除 NOTSET 以外的值,则返回该值。 否则,将向根遍历层次结构,直到找到除 NOTSET 以外的值,然后返回该值。 返回的值是一个整数,通常是 logging.DEBUGlogging.INFO 等之一。

getChild(suffix)

返回一个记录器,它是此记录器的后代,由后缀决定。 因此,logging.getLogger('abc').getChild('def.ghi') 将返回与 logging.getLogger('abc.def.ghi') 返回相同的记录器。 这是一个方便的方法,当使用例如命名父记录器时很有用 __name__ 而不是文字字符串。

3.2 版中的新功能。

debug(msg, *args, **kwargs)

在此记录器上记录级别为 DEBUG 的消息。 msg 是消息格式字符串,args 是使用字符串格式化操作符合并到 msg 中的参数。 (请注意,这意味着您可以在格式字符串中使用关键字以及单个字典参数。)

kwargs 中检查了三个关键字参数:exc_infostack_infoextra

如果 exc_info 未评估为 false,则会导致将异常信息添加到日志消息中。 如果提供了异常元组(以 sys.exc_info() 返回的格式)或异常实例,则使用它; 否则,调用 sys.exc_info() 获取异常信息。

第二个可选关键字参数是 stack_info,默认为 False。 如果为 true,堆栈信息将添加到日志消息中,包括实际的日志调用。 注意,这与指定exc_info显示的栈信息不同:前者是从栈底到当前线程的日志调用的栈帧,后者是关于栈的信息在搜索异常处理程序时出现异常后已展开的帧。

您可以独立于 exc_info 指定 stack_info,例如 仅显示您如何到达代码中的某个点,即使没有引发异常。 堆栈帧打印在标题行之后,该行表示:

Stack (most recent call last):

这模仿了显示异常帧时使用的 Traceback (most recent call last):

第三个关键字参数是 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

extra 中传递的字典中的键不应与日志系统使用的键发生冲突。 (有关日志系统使用哪些键的更多信息,请参阅 Formatter 文档。)

如果您选择在记录的消息中使用这些属性,则需要小心谨慎。 例如,在上面的例子中,Formatter 已经设置了一个格式字符串,它在 LogRecord 的属性字典中需要 'clientip' 和 'user'。 如果缺少这些,则不会记录该消息,因为会发生字符串格式异常。 因此,在这种情况下,您始终需要使用这些键传递 extra 字典。

虽然这可能很烦人,但此功能旨在用于特殊情况,例如多线程服务器,其中相同的代码在许多上下文中执行,并且出现的有趣条件取决于此上下文(例如远程客户端 IP 地址和经过身份验证的用户名,在上面的例子中)。 在这种情况下,专门的 Formatter 很可能与特定的 Handler 一起使用。

3.2 新功能: 增加了 stack_info 参数。

3.5 版更改: exc_info 参数现在可以接受异常实例。

info(msg, *args, **kwargs)

在此记录器上记录级别为 INFO 的消息。 这些参数被解释为 debug()

warning(msg, *args, **kwargs)

在此记录器上记录级别为 WARNING 的消息。 这些参数被解释为 debug()

笔记

有一个过时的方法 warn,它在功能上与 warning 相同。 由于 warn 已被弃用,请不要使用它 - 请改用 warning

error(msg, *args, **kwargs)

在此记录器上记录级别为 ERROR 的消息。 这些参数被解释为 debug()

critical(msg, *args, **kwargs)

在此记录器上记录级别为 CRITICAL 的消息。 这些参数被解释为 debug()

log(lvl, msg, *args, **kwargs)

在此记录器上记录整数级别 lvl 的消息。 其他参数被解释为 debug()

exception(msg, *args, **kwargs)

在此记录器上记录级别为 ERROR 的消息。 这些参数被解释为 debug()。 异常信息被添加到日志消息中。 此方法只能从异常处理程序中调用。

addFilter(filter)

将指定的过滤器 filter 添加到此记录器。

removeFilter(filter)

从此记录器中删除指定的过滤器 filter

filter(record)

将此记录器的过滤器应用于记录并在要处理记录时返回真值。 依次查询过滤器,直到其中之一返回假值。 如果它们都没有返回 false 值,则记录将被处理(传递给处理程序)。 如果返回假值,则不会对记录进行进一步处理。

addHandler(hdlr)

将指定的处理程序 hdlr 添加到此记录器。

removeHandler(hdlr)

从此记录器中删除指定的处理程序 hdlr

findCaller(stack_info=False)

查找调用者的源文件名和行号。 以 4 元素元组的形式返回文件名、行号、函数名和堆栈信息。 堆栈信息返回为 None,除非 stack_infoTrue

handle(record)

通过将记录传递给与此记录器及其祖先关联的所有处理程序来处理记录(直到发现 propagate 的假值)。 此方法用于从套接字接收到的 unpickled 记录,以及那些在本地创建的记录。 使用 filter() 应用记录器级过滤。

makeRecord(name, lvl, fn, lno, msg, args, exc_info, func=None, extra=None, sinfo=None)

这是一个工厂方法,可以在子类中重写以创建专门的 LogRecord 实例。

hasHandlers()

检查此记录器是否配置了任何处理程序。 这是通过在该记录器及其在记录器层次结构中的父级中查找处理程序来完成的。 如果找到处理程序,则返回 True,否则返回 False。 每当找到“propagate”属性设置为 false 的记录器时,该方法就会停止搜索层次结构 - 这将是最后一个检查处理程序是否存在的记录器。

3.2 版中的新功能。

3.7 版更改: 现在可以拾取和取消拾取记录器。


16.6.2. 日志级别

日志级别的数值如下表所示。 如果您想定义自己的级别,并且需要它们具有相对于预定义级别的特定值,那么这些主要是有用的。 如果您定义一个具有相同数值的级别,它会覆盖预定义的值; 预定义的名称丢失。

等级 数值
CRITICAL 50
ERROR 40
WARNING 30
INFO 20
DEBUG 10
NOTSET 0


16.6.3. 处理程序对象

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

class logging.Handler
__init__(level=NOTSET)

通过设置其级别、将过滤器列表设置为空列表并创建锁(使用 createLock())来初始化 Handler 实例以序列化对 I/O 机制的访问。

createLock()

初始化一个线程锁,该锁可用于序列化对可能不是线程安全的底层 I/O 功能的访问。

acquire()

获取用 createLock() 创建的线程锁。

release()

释放用 acquire() 获取的线程锁。

setLevel(level)

将此处理程序的阈值设置为 级别 。 低于 级别 的日志消息将被忽略。 创建处理程序时,级别设置为 NOTSET(这会导致处理所有消息)。

有关级别列表,请参阅 日志级别

3.2 版更改: level 参数现在接受级别的字符串表示形式,例如“INFO”,作为整数常量(例如 INFO)的替代。

setFormatter(fmt)

将此处理程序的 Formatter 设置为 fmt

addFilter(filter)

将指定的过滤器 filter 添加到此处理程序。

removeFilter(filter)

从此处理程序中删除指定的过滤器 filter

filter(record)

将此处理程序的过滤器应用于记录并在要处理记录时返回真值。 依次查询过滤器,直到其中之一返回假值。 如果它们都没有返回 false 值,则将发出记录。 如果返回一个 false 值,处理程序将不会发出记录。

flush()

确保已刷新所有日志记录输出。 这个版本什么都不做,打算由子类实现。

close()

整理处理程序使用的所有资源。 此版本不输出但会从内部处理程序列表中删除处理程序,该处理程序在调用 shutdown() 时关闭。 子类应确保从重写的 close() 方法调用它。

handle(record)

根据可能已添加到处理程序的过滤器,有条件地发出指定的日志记录。 使用 I/O 线程锁的获取/释放来包装记录的实际发射。

handleError(record)

emit() 调用期间遇到异常时,应从处理程序调用此方法。 如果模块级属性 raiseExceptionsFalse,异常会被默默忽略。 这是日志系统最需要的——大多数用户不会关心日志系统中的错误,他们对应用程序错误更感兴趣。 但是,如果您愿意,您可以将其替换为自定义处理程序。 指定的记录是发生异常时正在处理的记录。 (raiseExceptions 的默认值为 True,因为这在开发过程中更有用)。

format(record)

对记录进行格式化 - 如果设置了格式化程序,请使用它。 否则,请使用模块的默认格式化程序。

emit(record)

不惜一切代价实际记录指定的日志记录。 此版本旨在由子类实现,因此引发 NotImplementedError

有关标准包含的处理程序列表,请参阅 logging.handlers


16.6.4. 格式化程序对象

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

格式化程序可以使用格式字符串进行初始化,该格式字符串利用 LogRecord 属性的知识 - 例如上面提到的默认值,利用用户的消息和参数预先格式化为 [ X248X]LogRecord 的 message 属性。 此格式字符串包含标准 Python %-s 样式映射键。 有关字符串格式的更多信息,请参见 printf-style String Formatting 部分。

LogRecord 中有用的映射键在 LogRecord 属性 部分中给出。

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

返回 Formatter 类的新实例。 该实例使用整个消息的格式字符串以及消息的日期/时间部分的格式字符串进行初始化。 如果未指定 fmt,则使用 '%(message)s'。 如果未指定 datefmt,则使用 formatTime() 文档中描述的格式。

style 参数可以是 '%'、'{' 或 '$' 之一,并确定格式字符串将如何与其数据合并:使用 %-formatting 之一,str.format ()string.Template。 有关对日志消息使用 {- 和 $-formatting 的更多信息,请参阅 在整个应用程序中使用特定格式样式

3.2 版更改: 添加了 style 参数。

format(record)

记录的属性字典用作字符串格式化操作的操作数。 返回结果字符串。 在格式化字典之前,需要执行几个准备步骤。 记录的 message 属性是使用 msg % args 计算的。 如果格式化字符串包含 '(asctime)',则调用 formatTime() 来格式化事件时间。 如果有异常信息,则使用 formatException() 进行格式化并附加到消息中。 注意格式化的异常信息缓存在属性exc_text中。 这很有用,因为异常信息可以被腌制并通过网络发送,但是如果您有多个 Formatter 子类来自定义异常信息的格式,则应该小心。 在这种情况下,您必须在格式化程序完成格式化后清除缓存值,以便下一个处理事件的格式化程序不使用缓存值而是重新计算它。

如果堆栈信息可用,则将其附加在异常信息之后,必要时使用 formatStack() 对其进行转换。

formatTime(record, datefmt=None)

这个方法应该由想要利用格式化时间的格式化程序从 format() 调用。 可以在格式化程序中重写此方法以提供任何特定要求,但基本行为如下:如果指定了 datefmt(字符串),则与 time.strftime()[ X203X] 来格式化记录的创建时间。 否则,使用格式 '%Y-%m-%d %H:%M:%S,uuu',其中 uuu 部分是毫秒值,其他字母按照 time.strftime( ) 文档。 这种格式的示例时间是 2003-01-23 00:29:50,411。 返回结果字符串。

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

3.3 版更改: 以前,默认格式是硬编码的,如本例所示: 2010-09-06 22:38:15,292 其中逗号前的部分由 strptime 格式字符串处理 ('%Y-%m-%d %H:%M:%S' ]),逗号后面的部分是毫秒值。 因为 strptime 没有用于毫秒的格式占位符,毫秒值使用另一个格式字符串附加,'%s,%03d' - 这两个格式字符串都已硬编码到此方法中。 随着更改,这些字符串被定义为类级别属性,可以在需要时在实例级别覆盖。 属性的名称是 default_time_format(用于 strptime 格式字符串)和 default_msec_format(用于附加毫秒值)。

formatException(exc_info)

将指定的异常信息(sys.exc_info() 返回的标准异常元组)格式化为字符串。 此默认实现仅使用 traceback.print_exception()。 返回结果字符串。

formatStack(stack_info)

将指定的堆栈信息(由 traceback.print_stack() 返回的字符串,但删除最后一个换行符)格式化为字符串。 此默认实现仅返回输入值。


16.6.5. 过滤对象

Filters 可以被 HandlersLoggers 用于比级别提供的更复杂的过滤。 基本过滤器类只允许低于记录器层次结构中某个点的事件。 例如,用“A.B”初始化的过滤器将允许记录器“A.B”、“ABC”、“ABCD”、“ABD”等记录的事件。 但不是“A.BB”、“BAB”等。 如果用空字符串初始化,则传递所有事件。

class logging.Filter(name=)
返回 Filter 类的实例。 如果指定了 name,它会命名一个记录器,该记录器及其子项将允许其事件通过过滤器。 如果 name 是空字符串,则允许每个事件。
filter(record)
是否要记录指定的记录? 否返回零,是非零。 如果认为合适,可以通过这种方法就地修改记录。

请注意,在处理程序发出事件之前,会参考附加到处理程序的过滤器,而在记录事件时会参考附加到记录器的过滤器(使用 debug(), info()等),然后再向处理程序发送事件。 这意味着由后代记录器生成的事件不会被记录器的过滤器设置过滤,除非过滤器也已应用于这些后代记录器。

您实际上不需要子类化 Filter:您可以传递具有相同语义的 filter 方法的任何实例。

在 3.2 版更改: 您不需要创建专门的 Filter 类,或使用具有 filter 方法的其他类:您可以使用函数(或其他可调用的) 作为过滤器。 过滤逻辑将检查过滤器对象是否有 filter 属性:如果有,则假定为 Filter 并调用其 filter() 方法. 否则,它被假定为可调用的,并以记录作为单个参数进行调用。 返回值应符合 filter() 返回的值。


尽管过滤器主要用于根据比级别更复杂的标准过滤记录,但它们可以查看由它们所附加的处理程序或记录器处理的每条记录:如果您想执行诸如计算数量之类的操作,这可能很有用记录由特定的记录器或处理程序处理,或者在正在处理的 LogRecord 中添加、更改或删除属性。 显然,更改 LogRecord 需要小心谨慎,但它确实允许将上下文信息注入日志(请参阅 使用过滤器传递上下文信息 )。


16.6.6. 日志记录对象

LogRecord 实例在每次记录时由 Logger 自动创建,并且可以通过 makeLogRecord() 手动创建(例如,从接收到的腌制事件在电线上)。

class logging.LogRecord(name, level, pathname, lineno, msg, args, exc_info, func=None, sinfo=None)

包含与正在记录的事件相关的所有信息。

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

参数
  • name – 用于记录此 LogRecord 表示的事件的记录器的名称。 请注意,此名称将始终具有此值,即使它可能由附加到不同(祖先)记录器的处理程序发出。

  • level – 日志事件的数字级别(DEBUG、INFO 等之一)请注意,这将转换为 LogRecord 的 two 属性:levelno 用于数值和对应级别名称的 levelname

  • pathname – 进行日志记录调用的源文件的完整路径名。

  • lineno – 源文件中进行日志调用的行号。

  • msg – 事件描述消息,可能是带有变量数据占位符的格式字符串。

  • args – 要合并到 msg 参数中以获得事件描述的变量数据。

  • exc_info – 具有当前异常信息的异常元组,如果没有异常信息可用,则为 None

  • func – 调用日志记录调用的函数或方法的名称。

  • sinfo – 一个文本字符串,表示从当前线程中的堆栈底部到日志调用的堆栈信息。

getMessage()

在将任何用户提供的参数与消息合并后,返回此 LogRecord 实例的消息。 如果记录调用的用户提供的消息参数不是字符串,则对其调用 str() 以将其转换为字符串。 这允许使用用户定义的类作为消息,其 __str__ 方法可以返回要使用的实际格式字符串。

在 3.2 版更改:通过提供用于创建记录的工厂,使 LogRecord 的创建更具可配置性。 可以使用 getLogRecordFactory()setLogRecordFactory() 设置工厂(工厂签名见这里)。

此功能可用于在创建时将您自己的值注入 LogRecord。 您可以使用以下模式:

old_factory = logging.getLogRecordFactory()

def record_factory(*args, **kwargs):
    record = old_factory(*args, **kwargs)
    record.custom_attribute = 0xdecafbad
    return record

logging.setLogRecordFactory(record_factory)

使用这种模式,可以链接多个工厂,只要它们不覆盖彼此的属性或无意中覆盖上面列出的标准属性,应该不会有什么意外。


16.6.7. 日志记录属性

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

如果您使用 {} 格式 (str.format()),您可以使用 {attrname} 作为格式字符串中的占位符。 如果您使用 $-formatting (string.Template),请使用 ${attrname} 形式。 在这两种情况下,当然,将 attrname 替换为您要使用的实际属性名称。

在 {} 格式的情况下,您可以通过将它们放在属性名称之后来指定格式标志,并用冒号将其分隔。 例如:{msecs:03d} 的占位符会将 4 的毫秒值格式化为 004。 有关可用选项的完整详细信息,请参阅 str.format() 文档。

属性名称 格式 描述
参数 你不应该需要自己格式化。 参数元组合并到 msg 中以生成 message,或者其值用于合并的字典(当只有一个参数时,它是一个字典)。
上升时间 %(asctime)s 创建 LogRecord 的人类可读时间。 默认情况下,这是“2003-07-08 16:49:45,896”的形式(逗号后面的数字是时间的毫秒部分)。
创建 %(created)f 创建 LogRecord 的时间(由 time.time() 返回)。
exc_info 你不应该需要自己格式化。 异常元组 (à la sys.exc_info) 或者,如果没有发生异常,None
文件名 %(filename)s pathname 的文件名部分。
函数名 %(funcName)s 包含日志调用的函数名称。
级别名称 %(levelname)s 消息的文本记录级别('DEBUG''INFO''WARNING''ERROR''CRITICAL')。
水平诺 %(levelno)s 消息的数字日志记录级别(DEBUGINFOWARNINGERRORCRITICAL)。
线诺 %(lineno)d 发出日志记录调用的源行号(如果可用)。
信息 %(message)s 记录的消息,计算为 msg % args。 这是在调用 Formatter.format() 时设置的。
模块 %(module)s 模块(filename 的名称部分)。
毫秒 %(msecs)d 创建 LogRecord 的时间的毫秒部分。
留言 你不应该需要自己格式化。 在原始日志记录调用中传递的格式字符串。 与 args 合并生成 message 或任意对象(请参阅 使用任意对象作为消息 )。
名称 %(name)s 用于记录呼叫的记录器的名称。
路径名 %(pathname)s 发出日志记录调用的源文件的完整路径名(如果可用)。
过程 %(process)d 进程 ID(如果可用)。
进程名 %(processName)s 进程名称(如果可用)。
相对创建 %(relativeCreated)d 创建 LogRecord 的时间(以毫秒为单位),相对于加载日志记录模块的时间。
堆栈信息 你不应该需要自己格式化。 从当前线程中的堆栈底部到并包括导致创建此记录的日志记录调用的堆栈帧的堆栈帧信息(如果可用)。
线 %(thread)d 线程 ID(如果可用)。
线程名 %(threadName)s 线程名称(如果可用)。

3.1 版更改:添加了 processName


16.6.8. 记录器适配器对象

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

class logging.LoggerAdapter(logger, extra)
返回一个 LoggerAdapter 的实例,该实例用底层 Logger 实例和一个类似 dict 的对象初始化。
process(msg, kwargs)
修改传递给日志记录调用的消息和/或关键字参数,以插入上下文信息。 此实现将作为 extra 传递给构造函数的对象使用键 'extra' 添加到 kwargs。 返回值是一个 (msg, kwargs) 元组,其中包含传入参数的(可能已修改)版本。

LoggerAdapter支持Logger的以下方法: debug(), info(), warning (), error(), exception(), critical(), log(), isEnabledFor ()getEffectiveLevel()setLevel()hasHandlers()。 这些方法与 Logger 中的对应方法具有相同的签名,因此您可以互换使用这两种类型的实例。

3.2 版更改:isEnabledFor()getEffectiveLevel()setLevel()hasHandlers() ] 方法被添加到 LoggerAdapter。 这些方法委托给底层记录器。


16.6.9. 线程安全

日志模块旨在是线程安全的,而无需其客户端完成任何特殊工作。 它通过使用线程锁实现了这一点; 有一个锁来序列化对模块共享数据的访问,每个处理程序还创建一个锁来序列化对其底层 I/O 的访问。

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


16.6.10. 模块级函数

除了上面描述的类之外,还有许多模块级函数。

logging.getLogger(name=None)

返回具有指定名称的记录器,或者,如果名称是 None,则返回一个记录器,它是层次结构的根记录器。 如果指定,名称通常是点分隔的分层名称,如 aa.babcd。 这些名称的选择完全取决于使用日志记录的开发人员。

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

logging.getLoggerClass()

返回标准 Logger 类,或传递给 setLoggerClass() 的最后一个类。 可以从新的类定义中调用此函数,以确保安装自定义的 Logger 类不会撤消其他代码已应用的自定义。 例如:

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

返回一个用于创建 LogRecord 的可调用对象。

3.2 新功能: 该函数与 setLogRecordFactory() 一起提供,允许开发人员更好地控制表示日志事件的 LogRecord 的构造方式.

有关如何调用工厂的更多信息,请参阅 setLogRecordFactory()

logging.debug(msg, *args, **kwargs)

在根记录器上记录级别为 DEBUG 的消息。 msg 是消息格式字符串,args 是使用字符串格式化操作符合并到 msg 中的参数。 (请注意,这意味着您可以在格式字符串中使用关键字以及单个字典参数。)

kwargs 中有三个被检查的关键字参数: exc_info 如果它不评估为假,则会导致将异常信息添加到日志消息中。 如果提供了异常元组(以 sys.exc_info() 返回的格式)或异常实例,则使用它; 否则,调用 sys.exc_info() 获取异常信息。

第二个可选关键字参数是 stack_info,默认为 False。 如果为 true,堆栈信息将添加到日志消息中,包括实际的日志调用。 注意,这与指定exc_info显示的栈信息不同:前者是从栈底到当前线程的日志调用的栈帧,后者是关于栈的信息在搜索异常处理程序时出现异常后已展开的帧。

您可以独立于 exc_info 指定 stack_info,例如 仅显示您如何到达代码中的某个点,即使没有引发异常。 堆栈帧打印在标题行之后,该行表示:

Stack (most recent call last):

这模仿了显示异常帧时使用的 Traceback (most recent call last):

第三个可选关键字参数是 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

extra 中传递的字典中的键不应与日志系统使用的键发生冲突。 (有关日志系统使用哪些键的更多信息,请参阅 Formatter 文档。)

如果您选择在记录的消息中使用这些属性,则需要小心谨慎。 例如,在上面的例子中,Formatter 已经设置了一个格式字符串,它在 LogRecord 的属性字典中需要 'clientip' 和 'user'。 如果缺少这些,则不会记录该消息,因为会发生字符串格式异常。 因此,在这种情况下,您始终需要使用这些键传递 extra 字典。

虽然这可能很烦人,但此功能旨在用于特殊情况,例如多线程服务器,其中相同的代码在许多上下文中执行,并且出现的有趣条件取决于此上下文(例如远程客户端 IP 地址和经过身份验证的用户名,在上面的例子中)。 在这种情况下,专门的 Formatter 很可能与特定的 Handler 一起使用。

3.2 新功能: 增加了 stack_info 参数。

logging.info(msg, *args, **kwargs)
在根记录器上记录级别为 INFO 的消息。 这些参数被解释为 debug()
logging.warning(msg, *args, **kwargs)

在根记录器上记录级别为 WARNING 的消息。 这些参数被解释为 debug()

笔记

有一个过时的功能 warn,它在功能上与 warning 相同。 由于 warn 已被弃用,请不要使用它 - 请改用 warning

logging.error(msg, *args, **kwargs)
在根记录器上记录级别为 ERROR 的消息。 这些参数被解释为 debug()
logging.critical(msg, *args, **kwargs)
在根记录器上记录级别为 CRITICAL 的消息。 这些参数被解释为 debug()
logging.exception(msg, *args, **kwargs)
在根记录器上记录级别为 ERROR 的消息。 这些参数被解释为 debug()。 异常信息被添加到日志消息中。 此函数只能从异常处理程序中调用。
logging.log(level, msg, *args, **kwargs)

在根记录器上记录级别为 level 的消息。 其他参数被解释为 debug()

笔记

上面委托给根记录器的模块级便利函数调用 basicConfig() 以确保至少有一个处理程序可用。 因此,在 2.7.1 和 3.2 之前的 Python 版本中,它们应该 用于线程中,除非在 之前至少将一个处理程序添加到根记录器 线程启动。 在早期版本的 Python 中,由于 basicConfig() 中的线程安全缺陷,这可能(在极少数情况下)导致处理程序被多次添加到根记录器中,进而导致多条消息对于同一事件。

logging.disable(lvl=CRITICAL)

为所有记录器提供覆盖级别 lvl,该级别优先于记录器自己的级别。 当需要临时限制整个应用程序的日志输出时,此功能会很有用。 它的作用是禁用所有严重性为 lvl 及以下的日志调用,因此如果您使用 INFO 值调用它,则所有 INFO 和 DEBUG 事件都将被丢弃,而严重性为 WARNING 及以上的事件将被丢弃根据记录仪的有效级别进行处理。 如果 logging.disable(logging.NOTSET) 被调用,它会有效地删除这个覆盖级别,因此日志输出再次取决于单个记录器的有效级别。

请注意,如果您定义了高于 CRITICAL 的任何自定义日志记录级别(不推荐这样做),您将无法依赖 lvl 参数的默认值,但会必须明确提供合适的值。

3.7 版本更改: lvl 参数默认为 CRITICAL 级。 有关此更改的更多信息,请参阅问题 #28524。

logging.addLevelName(lvl, levelName)

将级别 lvl 与内部字典中的文本 levelName 相关联,用于将数字级别映射到文本表示,例如当 Formatter 格式化消息时。 此功能还可用于定义您自己的级别。 唯一的限制是所有使用的级别都必须使用此函数注册,级别应该是正整数,并且它们应该按照严重性递增的顺序增加。

笔记

如果您正在考虑定义自己的级别,请参阅有关 自定义级别 的部分。

logging.getLevelName(lvl)

返回日志级别 lvl 的文本表示。 如果级别是预定义级别 CRITICALERRORWARNINGINFODEBUG 之一,那么您将获得相应的字符串。 如果您使用 addLevelName() 将级别与名称关联,则返回与 lvl 关联的名称。 如果传入与定义级别之一对应的数值,则返回相应的字符串表示形式。 否则,返回字符串 'Level %s' % lvl。

笔记

级别是内部整数(因为它们需要在日志逻辑中进行比较)。 此函数用于通过 %(levelname)s 格式说明符(请参阅 LogRecord 属性 )在整数级别和格式化日志输出中显示的级别名称之间进行转换。

3.4 版本变化: 在 Python 3.4 之前的版本中,该函数也可以传递一个文本级别,并会返回该级别对应的数值。 这种未记录的行为被认为是一个错误,并在 Python 3.4 中被删除,但由于保留向后兼容性而在 3.4.2 中恢复。

logging.makeLogRecord(attrdict)
创建并返回一个新的 LogRecord 实例,其属性由 attrdict 定义。 此函数可用于获取通过套接字发送的腌制 LogRecord 属性字典,并在接收端将其重构为 LogRecord 实例。
logging.basicConfig(**kwargs)

通过使用默认的 Formatter 创建 StreamHandler 并将其添加到根记录器,为日志记录系统进行基本配置。 函数 debug()info()warning()error()critical()如果没有为根记录器定义处理程序,] 将自动调用 basicConfig()

如果根记录器已经为其配置了处理程序,则此函数不执行任何操作。

笔记

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

支持以下关键字参数。

格式

描述

文件名

指定使用指定的文件名创建 FileHandler,而不是 StreamHandler。

文件模式

如果指定了filename,则以模式打开文件。 默认为 'a'

格式

为处理程序使用指定的格式字符串。

日期文件

使用 time.strftime() 接受的指定日期/时间格式。

风格

如果指定了 format,则对格式字符串使用此样式。 '%''{''$' 之一用于 printf-stylestr.format()string。分别为模板。 默认为 '%'

等级

将根记录器级别设置为指定的 级别

溪流

使用指定的流来初始化 StreamHandler。 请注意,此参数与 filename 不兼容 - 如果两者都存在,则会引发 ValueError

处理程序

如果指定,这应该是已创建的处理程序的迭代,以添加到根记录器。 任何尚未设置格式化程序的处理程序都将被分配在此函数中创建的默认格式化程序。 请注意,此参数与 filenamestream 不兼容 - 如果两者都存在,则会引发 ValueError

3.2 版更改: 添加了 style 参数。

3.3 版更改: 添加了 处理程序 参数。 添加了额外的检查以捕获指定了不兼容参数的情况(例如 handlersstreamfilename,或 streamfilename)。

logging.shutdown()
通知日志系统通过刷新和关闭所有处理程序来执行有序关闭。 这应该在应用程序退出时调用,并且在此调用之后不应进一步使用日志记录系统。
logging.setLoggerClass(klass)
告诉日志系统在实例化记录器时使用类 klass。 该类应该定义 __init__(),这样只需要一个名称参数,并且 __init__() 应该调用 Logger.__init__()。 此函数通常在需要使用自定义记录器行为的应用程序实例化任何记录器之前调用。
logging.setLogRecordFactory(factory)

设置用于创建 LogRecord 的可调用对象。

参数

factory – 用于实例化日志记录的工厂调用。

3.2 新功能: 该函数与 getLogRecordFactory() 一起提供,允许开发者更好地控制表示日志事件的 LogRecord 的构造方式.

工厂有以下签名:

factory(name, level, fn, lno, msg, args, exc_info, func=None, sinfo=None, **kwargs)

名称

记录器名称。

等级

日志记录级别(数字)。

fn

进行日志记录调用的文件的完整路径名。

输入法

进行日志记录调用的文件中的行号。

留言

日志消息。

参数

日志消息的参数。

exc_info

异常元组,或 None

功能

调用日志记录调用的函数或方法的名称。

信息

traceback.print_stack() 提供的堆栈回溯,显示了调用层次结构。

kwargs

额外的关键字参数。



16.6.11。 模块级属性

logging.lastResort

通过此属性可以使用“最后的处理程序”。 这是一个 StreamHandler 写入 sys.stderr 的级别为 WARNING,用于在没有任何日志配置的情况下处理日志事件。 最终结果只是将消息打印到 sys.stderr。 这取代了先前的错误消息,指出“找不到记录器 XYZ 的处理程序”。 如果由于某种原因需要更早的行为,可以将 lastResort 设置为 None

3.2 版中的新功能。


16.6.12. 与警告模块集成

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

logging.captureWarnings(capture)

此功能用于通过登录和注销来打开警告的捕获。

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

如果 captureFalse,则警告重定向到日志系统将停止,警告将重定向到其原始目的地(即 那些在 captureWarnings(True) 被调用之前生效的)。

也可以看看

模块 logging.config
日志模块的配置 API。
模块 logging.handlers
日志模块中包含的有用处理程序。
PEP 282 - 一个日志系统
描述此功能以包含在 Python 标准库中的提案。
原始 Python 日志记录包
这是 logging 包的原始来源。 此站点提供的包版本适用于 Python 1.5.2、2.1.x 和 2.2.x,这些版本不包括标准库中的 logging 包。