logging.config — 日志配置

源代码: Lib/logging/config.py


本节介绍用于配置日志模块的 API。

配置函数

以下函数配置日志模块。它们位于 logging.config 模块中。它们的使用是可选的——你可以使用这些函数或调用主 API(在 logging 本身中定义)并定义在 logginglogging.handlers 中声明的处理器来配置日志模块。

logging.config.dictConfig(config)

从字典中获取日志配置。此字典的内容在下面的 配置字典模式 中描述。

如果在配置过程中遇到错误,此函数将引发 ValueErrorTypeErrorAttributeErrorImportError,并附带适当的描述性消息。以下是(可能不完整)的将引发错误的情况列表:

  • level 不是字符串,或者是一个不对应于实际日志级别的字符串。

  • propagate 值不是布尔值。

  • id 没有对应的目标。

  • 在增量调用期间找到不存在的处理器 id。

  • 无效的日志记录器名称。

  • 无法解析为内部或外部对象。

解析由 DictConfigurator 类执行,该类的构造函数传递用于配置的字典,并具有一个 configure() 方法。logging.config 模块具有一个可调用属性 dictConfigClass,该属性最初设置为 DictConfigurator。你可以用你自己的合适实现替换 dictConfigClass 的值。

dictConfig() 调用 dictConfigClass 并传递指定的字典,然后调用返回对象上的 configure() 方法使配置生效

def dictConfig(config):
    dictConfigClass(config).configure()

例如,DictConfigurator 的子类可以在其自身的 __init__() 中调用 DictConfigurator.__init__(),然后设置自定义前缀,这些前缀可在后续的 configure() 调用中使用。dictConfigClass 将绑定到这个新的子类,然后可以像默认的、未定制的状态下那样调用 dictConfig()

3.2 版本新增。

logging.config.fileConfig(fname, defaults=None, disable_existing_loggers=True, encoding=None)

configparser 格式的文件中读取日志配置。文件的格式应如 配置文件格式 中所述。可以从应用程序多次调用此函数,允许最终用户从各种预先准备好的配置中进行选择(如果开发人员提供了一种机制来呈现选择并加载所选配置)。

如果文件不存在,将引发 FileNotFoundError,如果文件无效或为空,则引发 RuntimeError

参数:
  • fname – 一个文件名、一个类似文件的对象或一个派生自 RawConfigParser 的实例。如果传递了 RawConfigParser 派生的实例,则按原样使用。否则,将实例化一个 ConfigParser,并由它从 fname 中传递的对象读取配置。如果它有一个 readline() 方法,则假定它是一个类似文件的对象,并使用 read_file() 读取;否则,假定它是一个文件名并传递给 read()

  • defaults – 可以在此参数中指定要传递给 ConfigParser 的默认值。

  • disable_existing_loggers – 如果指定为 False,则在调用此函数时存在的日志记录器保持启用状态。默认值为 True,因为这以向后兼容的方式启用了旧的行为。此行为是禁用任何现有的非根日志记录器,除非它们或它们的祖先在日志配置中被明确命名。

  • encoding – 当 fname 是文件名时,用于打开文件的编码。

在 3.4 版本中更改:现在接受 RawConfigParser 子类的实例作为 fname 的值。这有助于

  • 使用配置文件,其中日志配置只是整个应用程序配置的一部分。

  • 使用从文件中读取的配置,然后由使用应用程序进行修改(例如,基于命令行参数或运行时环境的其他方面),然后再传递给 fileConfig

在 3.10 版本中变更: 添加了 encoding 参数。

在 3.12 版本中变更: 如果提供的文件不存在、无效或为空,则会引发异常。

logging.config.listen(port=DEFAULT_LOGGING_CONFIG_PORT, verify=None)

在指定的端口上启动一个套接字服务器,并监听新的配置。如果未指定端口,则使用模块的默认 DEFAULT_LOGGING_CONFIG_PORT。日志配置将作为适合由 dictConfig()fileConfig() 处理的文件发送。返回一个 Thread 实例,您可以在该实例上调用 start() 来启动服务器,并在适当的时候调用 join()。要停止服务器,请调用 stopListening()

如果指定了 verify 参数,则它应该是一个可调用对象,用于验证通过套接字接收的字节是否有效并应该处理。这可以通过加密和/或签名通过套接字发送的内容来完成,以便 verify 可调用对象可以执行签名验证和/或解密。verify 可调用对象使用单个参数(通过套接字接收的字节)调用,并且应返回要处理的字节,或者返回 None 以指示应丢弃该字节。返回的字节可以与传入的字节相同(例如,当仅进行验证时),或者它们可能完全不同(可能在执行解密的情况下)。

要将配置发送到套接字,请读取配置文件并将其作为字节序列发送到套接字,该字节序列以使用 struct.pack('>L', n) 以二进制形式打包的四字节长度字符串为前缀。

注意

由于配置的某些部分是通过 eval() 传递的,因此使用此函数可能会使用户面临安全风险。尽管该函数仅绑定到 localhost 上的套接字,因此不接受来自远程计算机的连接,但在某些情况下,不受信任的代码可能会在调用 listen() 的进程的帐户下运行。具体而言,如果调用 listen() 的进程在用户之间不能相互信任的多用户计算机上运行,则恶意用户可以通过简单地连接到受害者的 listen() 套接字并发送一个配置来运行攻击者想要在受害者进程中执行的任何代码,从而安排在受害者用户的进程中运行本质上是任意的代码。如果使用默认端口,则尤其容易做到这一点,但是即使使用不同的端口也不难。为了避免这种情况发生的风险,请使用 listen()verify 参数来防止应用无法识别的配置。

在 3.4 版本中变更: 添加了 verify 参数。

注意

如果您想将配置发送到监听器,而不会禁用现有的记录器,则需要使用 JSON 格式进行配置,这将使用 dictConfig() 进行配置。此方法允许您在发送的配置中将 disable_existing_loggers 指定为 False

logging.config.stopListening()

停止通过调用 listen() 创建的监听服务器。这通常在对 listen() 的返回值调用 join() 之前调用。

安全注意事项

日志配置功能试图提供便利,部分是通过提供将配置文件中的文本转换为日志配置中使用的 Python 对象的能力来实现的 - 例如,如 用户定义的对象 中所述。但是,这些相同的机制(从用户定义的模块导入可调用对象并使用配置中的参数调用它们)可用于调用您喜欢的任何代码,因此您应该极其谨慎地对待来自不受信任来源的配置文件,并在实际加载它们之前,确保加载它们不会发生任何不好的事情。

配置字典架构

描述日志配置需要列出要创建的各种对象以及它们之间的连接;例如,您可以创建一个名为“console”的处理程序,然后说名为“startup”的记录器会将其消息发送到“console”处理程序。这些对象不仅限于 logging 模块提供的对象,因为您可以编写自己的格式化程序或处理程序类。这些类的参数可能还需要包含外部对象,例如 sys.stderr。用于描述这些对象和连接的语法在下面的 对象连接 中定义。

字典架构详细信息

传递给 dictConfig() 的字典必须包含以下键

  • version - 设置为表示架构版本的整数值。目前唯一有效的值是 1,但是拥有此键可以使架构在保持向后兼容性的同时进行演变。

所有其他键都是可选的,但如果存在,它们将被解释如下所述。在下面所有提到“配置字典”的情况下,都将检查特殊的 '()' 键,以查看是否需要自定义实例化。如果是,则使用下面 用户定义的对象 中描述的机制来创建实例;否则,将使用上下文来确定要实例化的内容。

  • formatters - 对应的值将是一个字典,其中每个键都是一个格式化程序 ID,每个值都是一个描述如何配置对应的 Formatter 实例的字典。

    在配置字典中搜索以下可选键,这些键与传递给创建 Formatter 对象的参数相对应

    • format

    • datefmt

    • style

    • validate (自版本 >=3.8)

    • defaults (自版本 >=3.12)

    一个可选的 class 键表示格式化器的类名(使用点分隔的模块和类名)。实例化参数与 Formatter 的相同,因此此键最适用于实例化 Formatter 的自定义子类。例如,替代类可能以展开或压缩的格式呈现异常回溯。如果你的格式化器需要不同的或额外的配置键,你应该使用 用户定义的对象

  • filters - 对应的值将是一个字典,其中每个键是一个过滤器 ID,每个值是一个描述如何配置相应过滤器实例的字典。

    配置字典会搜索键 name(默认为空字符串),并用它来构造一个 logging.Filter 实例。

  • handlers - 对应的值将是一个字典,其中每个键是一个处理器 ID,每个值是一个描述如何配置相应处理器实例的字典。

    配置字典会搜索以下键:

    • class (必选)。这是处理器类的完整限定名称。

    • level (可选)。处理器的级别。

    • formatter (可选)。此处理器的格式化器 ID。

    • filters (可选)。此处理器的过滤器 ID 列表。

      在 3.11 版本中更改: filters 除了 ID 之外,还可以接受过滤器实例。

    所有其他键都作为关键字参数传递给处理器的构造函数。例如,给定以下代码片段:

    handlers:
      console:
        class : logging.StreamHandler
        formatter: brief
        level   : INFO
        filters: [allow_foo]
        stream  : ext://sys.stdout
      file:
        class : logging.handlers.RotatingFileHandler
        formatter: precise
        filename: logconfig.log
        maxBytes: 1024
        backupCount: 3
    

    ID 为 console 的处理器被实例化为 logging.StreamHandler,使用 sys.stdout 作为底层流。ID 为 file 的处理器被实例化为 logging.handlers.RotatingFileHandler,并带有关键字参数 filename='logconfig.log', maxBytes=1024, backupCount=3

  • loggers - 对应的值将是一个字典,其中每个键是一个记录器名称,每个值是一个描述如何配置相应记录器实例的字典。

    配置字典会搜索以下键:

    • level (可选)。记录器的级别。

    • propagate (可选)。记录器的传播设置。

    • filters (可选)。此记录器的过滤器 ID 列表。

      在 3.11 版本中更改: filters 除了 ID 之外,还可以接受过滤器实例。

    • handlers (可选)。此记录器的处理器 ID 列表。

    指定的记录器将根据指定的级别、传播、过滤器和处理器进行配置。

  • root - 这将是根记录器的配置。配置的处理方式与任何记录器相同,只是 propagate 设置不适用。

  • incremental - 是否将配置解释为对现有配置的增量。此值默认为 False,这意味着指定的配置将替换现有配置,其语义与现有 fileConfig() API 使用的相同。

    如果指定的值为 True,则按照 增量配置 部分中的描述处理配置。

  • disable_existing_loggers - 是否禁用任何现有的非根记录器。此设置与 fileConfig() 中同名的参数相呼应。如果不存在,则此参数默认为 True。如果 incrementalTrue,则忽略此值。

增量配置

为增量配置提供完全的灵活性是很困难的。例如,由于过滤器和格式化器等对象是匿名的,因此一旦设置了配置,就不可能在增强配置时引用这些匿名对象。

此外,一旦设置了配置,就没有充分的理由在运行时任意更改记录器、处理器、过滤器和格式化器的对象图;记录器和处理器的详细程度可以通过仅设置级别(以及在记录器的情况下,传播标志)来控制。在多线程环境中以安全的方式任意更改对象图是有问题的;虽然并非不可能,但其带来的好处不值得在实现中增加复杂性。

因此,当配置字典的 incremental 键存在且为 True 时,系统将完全忽略任何 formattersfilters 条目,并且仅处理 handlers 条目中的 level 设置,以及 loggersroot 条目中的 levelpropagate 设置。

在配置字典中使用值允许将配置作为 pickled 字典通过网络发送到套接字侦听器。因此,可以在无需停止和重启应用程序的情况下,随着时间的推移更改长时间运行的应用程序的日志详细程度。

对象连接

该模式描述了一组日志对象 - 记录器、处理器、格式化器、过滤器 - 它们在对象图中相互连接。因此,该模式需要表示对象之间的连接。例如,假设在配置完成后,特定的记录器附加了特定的处理器。为了便于讨论,我们可以说记录器表示源,而处理器表示这两个连接之间的目标。当然,在配置的对象中,这表示为记录器持有对处理器的引用。在配置字典中,这是通过给每个目标对象一个唯一标识它的 ID 来完成的,然后在源对象的配置中使用该 ID 来指示源对象和具有该 ID 的目标对象之间存在连接。

因此,例如,考虑以下 YAML 代码片段:

formatters:
  brief:
    # configuration for formatter with id 'brief' goes here
  precise:
    # configuration for formatter with id 'precise' goes here
handlers:
  h1: #This is an id
   # configuration of handler with id 'h1' goes here
   formatter: brief
  h2: #This is another id
   # configuration of handler with id 'h2' goes here
   formatter: precise
loggers:
  foo.bar.baz:
    # other configuration for logger 'foo.bar.baz'
    handlers: [h1, h2]

(注意:这里使用 YAML 是因为它比字典的等效 Python 源代码形式更易读。)

记录器的 ID 是以编程方式用于获取对这些记录器的引用的记录器名称,例如 foo.bar.baz。格式化器和过滤器的 ID 可以是任何字符串值(例如上面的 briefprecise),并且它们是瞬态的,因为它们仅在处理配置字典时有意义,用于确定对象之间的连接,并且在配置调用完成后不会持久保存在任何地方。

上面的代码片段表明,名为 foo.bar.baz 的记录器应该附加两个处理器,它们由处理器 ID h1h2 描述。h1 的格式化器是由 ID brief 描述的格式化器,h2 的格式化器是由 ID precise 描述的格式化器。

用户定义的对象

该模式支持用于处理器、过滤器和格式化器的用户定义对象。(记录器不需要针对不同的实例具有不同的类型,因此此配置模式不支持用户定义的记录器类。)

要配置的对象由详细说明其配置的字典描述。在某些情况下,日志系统可以从上下文中推断出如何实例化对象,但是当要实例化用户定义的对象时,系统将不知道如何执行此操作。为了为用户定义的对象实例化提供完全的灵活性,用户需要提供一个“工厂” - 一个可调用对象,该对象使用配置字典调用并返回实例化的对象。这通过在特殊键 '()' 下提供工厂的绝对导入路径来指示。这是一个具体的示例:

formatters:
  brief:
    format: '%(message)s'
  default:
    format: '%(asctime)s %(levelname)-8s %(name)-15s %(message)s'
    datefmt: '%Y-%m-%d %H:%M:%S'
  custom:
      (): my.package.customFormatterFactory
      bar: baz
      spam: 99.9
      answer: 42

上面的 YAML 代码片段定义了三个格式化器。第一个,ID 为 brief,是一个标准的 logging.Formatter 实例,具有指定的格式字符串。第二个,ID 为 default,具有更长的格式,并且还显式定义了时间格式,并且将导致使用这两个格式字符串初始化的 logging.Formatter。以 Python 源代码形式显示,briefdefault 格式化器具有配置子字典:

{
  'format' : '%(message)s'
}

{
  'format' : '%(asctime)s %(levelname)-8s %(name)-15s %(message)s',
  'datefmt' : '%Y-%m-%d %H:%M:%S'
}

分别地,由于这些字典不包含特殊键 '()',因此实例化是从上下文中推断出来的:结果,创建了标准的 logging.Formatter 实例。第三个格式化器(ID 为 custom)的配置子字典为:

{
  '()' : 'my.package.customFormatterFactory',
  'bar' : 'baz',
  'spam' : 99.9,
  'answer' : 42
}

并且此字典包含特殊键 '()',这意味着需要用户定义的实例化。在这种情况下,将使用指定的工厂可调用对象。如果它是一个实际的可调用对象,它将被直接使用 - 否则,如果你指定一个字符串(如示例中所示),将使用正常的导入机制来定位实际的可调用对象。可调用对象将使用配置子字典中的 剩余 项作为关键字参数进行调用。在上面的示例中,ID 为 custom 的格式化器将被假定为由以下调用返回:

my.package.customFormatterFactory(bar='baz', spam=99.9, answer=42)

警告

在上面的示例中,诸如 barspamanswer 等键的值不应是配置字典或引用,例如 cfg://fooext://bar,因为它们不会被配置机制处理,而是按原样传递给可调用对象。

'()' 被用作特殊键,因为它不是有效的关键字参数名称,因此不会与调用中使用的关键字参数名称冲突。'()' 也可以作为助记符,表示相应的值是可调用的。

在 3.11 版本中更改: handlersloggersfilters 成员除了 ID 之外,还可以接受过滤器实例。

您还可以指定一个特殊键 '.',其值是一个字典,用于映射属性名称到值。如果找到,指定的属性将在返回用户定义的对象之前设置。因此,使用以下配置

{
  '()' : 'my.package.customFormatterFactory',
  'bar' : 'baz',
  'spam' : 99.9,
  'answer' : 42,
  '.' {
    'foo': 'bar',
    'baz': 'bozz'
  }
}

返回的格式化程序将具有设置为 'bar' 的属性 foo 和设置为 'bozz' 的属性 baz

警告

在上面的示例中,诸如 foobaz 等属性的值不应是配置字典或引用,例如 cfg://fooext://bar,因为它们不会被配置机制处理,而是按原样设置为属性值。

处理程序配置顺序

处理程序按照其键的字母顺序配置,并且配置的处理程序将替换架构中 handlers 字典(工作副本)中的配置字典。如果您使用诸如 cfg://handlers.foo 之类的结构,那么最初 handlers['foo'] 指向名为 foo 的处理程序的配置字典,稍后(一旦配置了该处理程序)它会指向配置的处理程序实例。因此,cfg://handlers.foo 可以解析为字典或处理程序实例。一般来说,最好以这样一种方式命名处理程序,使得依赖的处理程序在它们所依赖的任何处理程序之后 _配置_ ;这允许在配置依赖于处理程序 foo 的处理程序时使用类似 cfg://handlers.foo 的东西。如果该依赖的处理程序被命名为 bar,则会产生问题,因为 bar 的配置将在 foo 的配置之前尝试,并且 foo 尚未配置。但是,如果依赖的处理程序被命名为 foobar,它将在 foo 之后配置,结果是 cfg://handlers.foo 将解析为已配置的处理程序 foo,而不是其配置字典。

访问外部对象

有时配置需要引用配置外部的对象,例如 sys.stderr。如果使用 Python 代码构造配置字典,这很简单,但是当通过文本文件(例如 JSON、YAML)提供配置时,就会出现问题。在文本文件中,没有标准方法可以将 sys.stderr 与字面字符串 'sys.stderr' 区分开来。为了方便这种区分,配置系统会在字符串值中查找某些特殊前缀并对其进行特殊处理。例如,如果字面字符串 'ext://sys.stderr' 作为配置中的值提供,那么 ext:// 将被剥离,值的其余部分将使用正常的导入机制进行处理。

这种前缀的处理方式类似于协议处理:有一个通用机制来查找与正则表达式 ^(?P<prefix>[a-z]+)://(?P<suffix>.*)$ 匹配的前缀,其中,如果 prefix 被识别,则 suffix 将以依赖于前缀的方式处理,并且处理的结果将替换字符串值。如果前缀未被识别,则字符串值将保持不变。

访问内部对象

除了外部对象之外,有时还需要引用配置中的对象。配置系统会隐式地为它知道的事物这样做。例如,记录器或处理程序中 level 的字符串值 'DEBUG' 将自动转换为值 logging.DEBUG,并且 handlersfiltersformatter 条目将采用对象 ID 并解析为相应的目标对象。

但是,对于 logging 模块未知的用户定义对象,需要更通用的机制。例如,考虑 logging.handlers.MemoryHandler,它接受一个 target 参数,该参数是另一个要委托的处理程序。由于系统已经知道这个类,那么在配置中,给定的 target 只需要是相关目标处理程序的对象 ID,系统将从 ID 解析到该处理程序。但是,如果用户定义了一个具有 alternate 处理程序的 my.package.MyHandler,配置系统将不知道 alternate 指的是处理程序。为了满足这一点,通用解析系统允许用户指定

handlers:
  file:
    # configuration of file handler goes here

  custom:
    (): my.package.MyHandler
    alternate: cfg://handlers.file

字面字符串 'cfg://handlers.file' 的解析方式与带有 ext:// 前缀的字符串类似,但在配置本身中查找而不是在导入命名空间中查找。该机制允许通过点或索引进行访问,类似于 str.format 提供的访问方式。因此,给定以下片段

handlers:
  email:
    class: logging.handlers.SMTPHandler
    mailhost: localhost
    fromaddr: [email protected]
    toaddrs:
      - [email protected]
      - [email protected]
    subject: Houston, we have a problem.

在配置中,字符串 'cfg://handlers' 将解析为键为 handlers 的字典,字符串 'cfg://handlers.email 将解析为 handlers 字典中键为 email 的字典,依此类推。字符串 'cfg://handlers.email.toaddrs[1] 将解析为 '[email protected]',字符串 'cfg://handlers.email.toaddrs[0]' 将解析为值 '[email protected]'subject 值可以使用 'cfg://handlers.email.subject' 或等效的 'cfg://handlers.email[subject]' 来访问。只有当键包含空格或非字母数字字符时才需要使用后一种形式。请注意,字符 [] 不允许出现在键中。如果索引值仅由十进制数字组成,则将尝试使用相应的整数值进行访问,如果需要,则回退到字符串值。

给定字符串 cfg://handlers.myhandler.mykey.123,它将解析为 config_dict['handlers']['myhandler']['mykey']['123']。如果字符串被指定为 cfg://handlers.myhandler.mykey[123],系统将尝试从 config_dict['handlers']['myhandler']['mykey'][123] 中检索值,如果失败,则回退到 config_dict['handlers']['myhandler']['mykey']['123']

导入解析和自定义导入器

默认情况下,导入解析使用内置的 __import__() 函数来进行导入。您可能希望用自己的导入机制替换它:如果是这样,您可以替换 DictConfigurator 或其超类 BaseConfigurator 类的 importer 属性。但是,您需要小心,因为函数是通过描述符从类中访问的。如果您使用 Python 可调用对象来进行导入,并且希望在类级别而不是实例级别定义它,则需要使用 staticmethod() 对其进行包装。例如

from importlib import import_module
from logging.config import BaseConfigurator

BaseConfigurator.importer = staticmethod(import_module)

如果您在配置器实例上设置导入可调用对象,则无需使用 staticmethod() 进行包装。

配置 QueueHandler 和 QueueListener

如果您想配置一个 QueueHandler,请注意,这通常与 QueueListener 结合使用,您可以将两者一起配置。配置完成后,QueueListener 实例将作为创建的处理程序的 listener 属性可用,并且您可以使用 getHandlerByName() 并传递您在配置中用于 QueueHandler 的名称来访问它。用于配置该对的字典模式如下面的 YAML 片段示例所示。

handlers:
  qhand:
    class: logging.handlers.QueueHandler
    queue: my.module.queue_factory
    listener: my.package.CustomListener
    handlers:
      - hand_name_1
      - hand_name_2
      ...

queuelistener 键是可选的。

如果存在 queue 键,则对应的值可以是以下之一

  • 一个实现 Queue.put_nowaitQueue.get 公共 API 的对象。例如,这可能是 queue.Queue 的实际实例或其子类,或通过 multiprocessing.managers.SyncManager.Queue() 获取的代理。

    当然,只有在代码中构造或修改配置字典时才有可能。

  • 一个字符串,解析为一个可调用对象,当不带参数调用时,返回要使用的队列实例。该可调用对象可以是 queue.Queue 子类或返回合适的队列实例的函数,例如 my.module.queue_factory()

  • 一个具有 '()' 键的字典,该字典以通常的方式构造,如 用户定义的对象 中所述。此构造的结果应为 queue.Queue 实例。

如果缺少 queue 键,则会创建并使用标准的无界 queue.Queue 实例。

如果存在 listener 键,则对应的值可以是以下之一

  • logging.handlers.QueueListener 的子类。当然,只有在代码中构造或修改配置字典时才有可能。

  • 一个字符串,解析为一个类,该类是 QueueListener 的子类,例如 'my.package.CustomListener'

  • 一个具有 '()' 键的字典,该字典以通常的方式构造,如 用户定义的对象 中所述。此构造的结果应为具有与 QueueListener 初始化器相同签名的可调用对象。

如果缺少 listener 键,则使用 logging.handlers.QueueListener

handlers 键下的值是配置中其他处理程序的名称(未在上面的代码片段中显示),这些处理程序将传递给队列监听器。

任何自定义的队列处理程序和监听器类都需要使用与 QueueHandlerQueueListener 相同的初始化签名进行定义。

在 3.12 版本中添加。

配置文件格式

fileConfig() 理解的配置文件格式基于 configparser 功能。该文件必须包含名为 [loggers][handlers][formatters] 的节,这些节按名称标识文件中定义的每种类型的实体。对于每个这样的实体,都有一个单独的节,用于标识该实体是如何配置的。因此,对于 [loggers] 节中名为 log01 的记录器,相关的配置详细信息保存在 [logger_log01] 节中。类似地,[handlers] 节中名为 hand01 的处理程序的配置保存在名为 [handler_hand01] 的节中,而 [formatters] 节中名为 form01 的格式化程序的配置在名为 [formatter_form01] 的节中指定。根记录器配置必须在名为 [logger_root] 的节中指定。

注意

fileConfig() API 比 dictConfig() API 更旧,并且不提供涵盖日志记录某些方面的功能。例如,您不能使用 fileConfig() 配置 Filter 对象,这些对象提供了超出简单整数级别的消息过滤。如果您的日志配置中需要 Filter 的实例,则需要使用 dictConfig()。请注意,对配置功能的未来增强将添加到 dictConfig(),因此在方便的时候考虑过渡到这个较新的 API 是值得的。

下面给出了文件中这些节的示例。

[loggers]
keys=root,log02,log03,log04,log05,log06,log07

[handlers]
keys=hand01,hand02,hand03,hand04,hand05,hand06,hand07,hand08,hand09

[formatters]
keys=form01,form02,form03,form04,form05,form06,form07,form08,form09

根记录器必须指定一个级别和处理程序列表。下面给出了根记录器节的示例。

[logger_root]
level=NOTSET
handlers=hand01

level 条目可以是 DEBUG、INFO、WARNING、ERROR、CRITICALNOTSET 之一。仅对于根记录器,NOTSET 表示将记录所有消息。级别值在 logging 包的命名空间上下文中进行评估

handlers 条目是一个逗号分隔的处理程序名称列表,这些名称必须出现在 [handlers] 节中。这些名称必须出现在 [handlers] 节中,并且在配置文件中具有对应的节。

对于根记录器以外的记录器,需要一些额外的信息。以下示例说明了这一点。

[logger_parser]
level=DEBUG
handlers=hand01
propagate=1
qualname=compiler.parser

levelhandlers 条目的解释方式与根记录器相同,但如果非根记录器的级别被指定为 NOTSET,系统会查询层次结构中更高级别的记录器,以确定该记录器的有效级别。propagate 条目设置为 1 表示消息必须从该记录器传播到记录器层次结构中更高级别的处理程序,设置为 0 表示消息不会传播到层次结构中更高级别的处理程序。qualname 条目是记录器的分层通道名称,也就是说,应用程序用来获取记录器的名称。

以下示例说明了指定处理程序配置的部分。

[handler_hand01]
class=StreamHandler
level=NOTSET
formatter=form01
args=(sys.stdout,)

class 条目指示处理程序的类(由 eval()logging 包的命名空间中确定)。level 的解释方式与记录器相同,NOTSET 被视为“记录一切”。

formatter 条目指示此处理程序的格式化器的键名。如果为空,则使用默认格式化器 (logging._defaultFormatter)。如果指定了名称,则它必须出现在 [formatters] 部分中,并且在配置文件中具有相应的节。

args 条目在 logging 包的命名空间中进行评估后,是处理程序类构造函数的参数列表。请参阅相关处理程序的构造函数,或下面的示例,了解如何构造典型的条目。如果未提供,则默认为 ()

可选的 kwargs 条目在 logging 包的命名空间中进行评估后,是处理程序类构造函数的关键字参数字典。如果未提供,则默认为 {}

[handler_hand02]
class=FileHandler
level=DEBUG
formatter=form02
args=('python.log', 'w')

[handler_hand03]
class=handlers.SocketHandler
level=INFO
formatter=form03
args=('localhost', handlers.DEFAULT_TCP_LOGGING_PORT)

[handler_hand04]
class=handlers.DatagramHandler
level=WARN
formatter=form04
args=('localhost', handlers.DEFAULT_UDP_LOGGING_PORT)

[handler_hand05]
class=handlers.SysLogHandler
level=ERROR
formatter=form05
args=(('localhost', handlers.SYSLOG_UDP_PORT), handlers.SysLogHandler.LOG_USER)

[handler_hand06]
class=handlers.NTEventLogHandler
level=CRITICAL
formatter=form06
args=('Python Application', '', 'Application')

[handler_hand07]
class=handlers.SMTPHandler
level=WARN
formatter=form07
args=('localhost', 'from@abc', ['user1@abc', 'user2@xyz'], 'Logger Subject')
kwargs={'timeout': 10.0}

[handler_hand08]
class=handlers.MemoryHandler
level=NOTSET
formatter=form08
target=
args=(10, ERROR)

[handler_hand09]
class=handlers.HTTPHandler
level=NOTSET
formatter=form09
args=('localhost:9022', '/log', 'GET')
kwargs={'secure': True}

以下示例说明了指定格式化器配置的部分。

[formatter_form01]
format=F1 %(asctime)s %(levelname)s %(message)s %(customfield)s
datefmt=
style=%
validate=True
defaults={'customfield': 'defaultvalue'}
class=logging.Formatter

格式化器配置的参数与字典模式 formatters 部分中的键相同。

defaults 条目在 logging 包的命名空间中进行评估后,是用于自定义格式化字段的默认值的字典。如果未提供,则默认为 None

注意

由于使用了上述的 eval(),通过套接字使用 listen() 发送和接收配置会产生潜在的安全风险。风险仅限于多个不互信的用户在同一台机器上运行代码的情况;有关更多信息,请参阅 listen() 文档。

另请参阅

模块 logging

logging 模块的 API 参考。

模块 logging.handlers

logging 模块包含的有用处理程序。