logging.config
---日志配置¶
本节介绍用于配置日志模块的API。
配置功能¶
以下功能配置日志记录模块。它们位于 logging.config
模块。它们的使用是可选的——您可以使用这些函数或通过调用主API(在中定义)来配置日志模块。 logging
以及定义在 logging
或 logging.handlers
.
- logging.config.dictConfig(config)¶
从字典获取日志配置。本词典的内容在 配置字典架构 下面。
如果在配置过程中遇到错误,此函数将引发
ValueError
,TypeError
,AttributeError
或ImportError
带有适当的描述性信息。以下是将引发错误的条件(可能不完整)列表:A
level
它不是字符串,或者它不是与实际日志记录级别不对应的字符串。A
propagate
不是布尔值的值。没有相应目标的ID。
在增量调用期间发现不存在的处理程序ID。
记录器名称无效。
无法解析为内部或外部对象。
解析由执行
DictConfigurator
类,其构造函数传递用于配置的字典,并具有configure()
方法。这个logging.config
模块具有可调用属性dictConfigClass
初始设置为DictConfigurator
. 您可以替换dictConfigClass
用你自己的一个合适的实现。dictConfig()
调用dictConfigClass
传递指定的字典,然后调用configure()
返回的对象上的方法以使配置生效::def dictConfig(config): dictConfigClass(config).configure()
例如,子类
DictConfigurator
可以调用DictConfigurator.__init__()
在它自己的__init__()
,然后设置自定义前缀,这些前缀将在后面的configure()
调用。dictConfigClass
将绑定到这个新的子类,然后dictConfig()
可以完全按照默认的非自定义状态调用。3.2 新版功能.
- logging.config.fileConfig(fname, defaults=None, disable_existing_loggers=True)¶
从中读取日志配置
configparser
格式化文件。文件格式应如中所述。 配置文件格式 . 可以从应用程序中多次调用此函数,从而允许最终用户从各种预屏蔽配置中进行选择(如果开发人员提供了一种呈现选择并加载所选配置的机制)。- 参数
fname -- 文件名、类似文件的对象或派生自
RawConfigParser
. 如果ARawConfigParser
-已传递派生实例,它将按原样使用。否则,AConfigparser
是实例化的,它从传入的对象中读取配置fname
. 如果有readline()
方法,假定它是一个类似文件的对象,并使用read_file()
;否则,假定它是一个文件名并传递给read()
.defaults -- 可以在此参数中指定要传递给configparser的默认值。
disable_existing_loggers -- 如果指定为
False
,当进行此调用时存在的记录器保持启用状态。默认值为True
因为这以向后兼容的方式启用了旧的行为。此行为用于禁用任何现有的非根记录器,除非它们或其祖先在日志配置中被显式命名。
在 3.4 版更改: 子类的实例
RawConfigParser
现在被接受为fname
. 这有助于:使用一个配置文件,其中日志配置只是整个应用程序配置的一部分。
使用从文件中读取的配置,然后由使用应用程序修改(例如,基于命令行参数或运行时环境的其他方面),然后再传递给
fileConfig
.
- logging.config.listen(port=DEFAULT_LOGGING_CONFIG_PORT, verify=None)¶
在指定端口上启动套接字服务器,并侦听新配置。如果没有指定端口,则模块的默认值为
DEFAULT_LOGGING_CONFIG_PORT
使用。日志配置将作为适合由处理的文件发送dictConfig()
或fileConfig()
. 返回AThread
可以调用的实例start()
启动服务器,您可以join()
在适当的时候。要停止服务器,请致电stopListening()
.这个
verify
参数(如果指定)应为可调用参数,该参数应验证通过套接字接收的字节是否有效并应进行处理。这可以通过对通过套接字发送的内容进行加密和/或签名来实现,这样verify
Callable可以执行签名验证和/或解密。这个verify
使用单个参数调用Callable(可调用),即通过套接字接收的字节数,并应返回要处理的字节数,或者None
以指示应丢弃字节。返回的字节可以与传入的字节相同(例如,仅在完成验证时),也可以完全不同(可能是在执行解密时)。要将配置发送到套接字,请读取配置文件并将其作为一个字节序列发送到套接字,该字节序列前面是一个以二进制形式打包的四字节长度字符串,使用
struct.pack('>L', n)
.注解
因为部分配置是通过
eval()
,使用此功能可能会给用户带来安全风险。而函数只绑定到上的套接字localhost
,因此不接受来自远程计算机的连接,在某些情况下,不受信任的代码可以在调用的进程的帐户下运行。listen()
. 具体来说,如果进程调用listen()
在多用户计算机上运行,在多用户计算机上,用户不能相互信任,那么恶意用户只需连接到受害者的进程,就可以安排在受害者的进程中运行基本上任意的代码。listen()
套接字并发送一个配置,该配置运行攻击者希望在受害者进程中执行的任何代码。这在使用默认端口时特别容易,但即使使用不同的端口也不难)。为了避免发生这种情况的风险,请使用verify
参数listen()
以防止应用未识别的配置。在 3.4 版更改: 这个
verify
已添加参数。注解
如果要向侦听器发送不禁用现有记录器的配置,则需要为配置使用JSON格式,该格式将使用
dictConfig()
用于配置。此方法允许您指定disable_existing_loggers
作为False
在您发送的配置中。
配置字典架构¶
描述日志配置需要列出要创建的各种对象以及它们之间的连接;例如,您可以创建一个名为“console”的处理程序,然后说名为“startup”的记录器将其消息发送到“console”处理程序。这些对象不限于 logging
模块,因为您可以编写自己的格式化程序或处理程序类。这些类的参数可能还需要包括外部对象,例如 sys.stderr
. 描述这些对象和连接的语法在 对象连接 下面。
字典架构详细信息¶
字典传给 dictConfig()
必须包含以下键:
版本 -设置为表示架构版本的整数值。目前唯一有效的值是1,但是拥有这个键允许模式在保持向后兼容性的同时发展。
所有其他键都是可选的,但如果存在,它们将按下面的说明进行解释。在下面提到“配置dict”的所有情况下,都将检查其是否具有 '()'
键查看是否需要自定义实例化。如果是这样,则 用户定义的对象 下面用于创建实例;否则,上下文用于确定要实例化的内容。
formatters -相应的值将是一个dict,其中每个键都是格式化程序ID,每个值都是一个dict,描述如何配置相应的
Formatter
实例。在配置字典中搜索与传递的参数相对应的以下可选键,以创建
Formatter
对象:format
datefmt
style
validate
(从版本>=3.8开始)
可选的
class
键指示格式化程序类的名称(以虚线模块和类名表示)。实例化参数与Formatter
,因此,此键对于实例化的自定义子类最有用Formatter
。例如,Alternative类可能以扩展或压缩格式显示异常回溯。如果格式化程序需要不同的或额外的配置键,则应使用 用户定义的对象 。过滤器 -相应的值将是一个dict,其中每个键都是一个过滤器ID,每个值都是一个dict,描述如何配置相应的过滤器实例。
在配置dict中搜索键
name
(默认为空字符串),它用于构造logging.Filter
实例。处理程序 -对应的值将是一个dict,其中每个键都是一个处理程序ID,每个值都是一个dict,描述如何配置对应的处理程序实例。
在配置dict中搜索以下键:
class
(强制性)。这是处理程序类的完全限定名。level
(可选)。处理程序的级别。formatter
(可选)。此处理程序的格式化程序的ID。filters
(可选)。此处理程序的筛选器ID列表。
所有 other 键作为关键字参数传递给处理程序的构造函数。例如,给定片段:
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 -对应的值将是一个dict,其中每个键都是一个记录器名称,每个值都是一个dict,描述如何配置对应的记录器实例。
在配置dict中搜索以下键:
level
(可选)。记录器的级别。propagate
(可选)。记录器的传播设置。filters
(可选)。此记录器的筛选器ID列表。handlers
(可选)。此记录器处理程序的ID列表。
将根据指定的级别、传播、筛选器和处理程序配置指定的记录器。
root -这将是根记录器的配置。配置的处理将与任何记录器相同,除了
propagate
设置将不适用。增量 -是否将配置解释为对现有配置的增量。此值默认为
False
,这意味着指定的配置使用与现有配置相同的语义替换现有配置。fileConfig()
应用程序编程接口。如果指定值为
True
,配置将按照上一节中的说明进行处理。 增量配置 .disable_existing_loggers -是否要禁用任何现有的非根记录器。此设置在中镜像相同名称的参数
fileConfig()
. 如果不存在,则此参数默认为True
. 如果 增量 是True
.
增量配置¶
很难为增量配置提供完全的灵活性。例如,由于过滤器和格式化程序等对象是匿名的,因此一旦设置了配置,就不可能在扩充配置时引用此类匿名对象。
此外,在运行时,一旦设置了一个配置,就没有一个令人信服的案例可以随意更改记录器、处理程序、过滤器、格式化程序的对象图;记录器和处理程序的冗长性可以通过设置级别来控制(对于记录器,还可以通过传播标志来控制)。在多线程环境中,以安全的方式随意更改对象图是有问题的;虽然这并非不可能,但其带来的好处并不值得在实现中增加复杂性。
因此,当 incremental
配置dict的键存在并且是 True
,系统将完全忽略 formatters
和 filters
并只处理 level
中的设置 handlers
条目,以及 level
和 propagate
中的设置 loggers
和 root
条目。
在配置dict中使用一个值,可以将配置作为泡菜dict通过线路发送到套接字侦听器。因此,长时间运行的应用程序的日志记录冗长性可以随着时间而改变,而无需停止和重新启动应用程序。
对象连接¶
该模式描述了一组记录对象——记录器、处理程序、格式化程序、过滤器——它们在对象图中相互连接。因此,模式需要表示对象之间的连接。例如,假设配置后,特定的记录器将特定的处理程序附加到它上。为了讨论这个问题,我们可以说记录器代表两个连接的源,而处理程序代表两个连接的目的。当然,在配置的对象中,这由保存对处理程序的引用的记录器表示。在配置dict中,这是通过给每个目标对象一个明确标识它的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可以是任何字符串值(例如 brief
, precise
上面)它们是暂时的,因为它们只对处理配置字典有意义,用于确定对象之间的连接,并且在配置调用完成时不会在任何地方持久化。
上面的代码段指示名为 foo.bar.baz
应该附加两个处理程序,由处理程序ID描述 h1
和 h2
. 的格式化程序 h1
是用身份证描述的吗 brief
和格式化程序 h2
是用身份证描述的吗 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片段定义了三个格式化程序。第一个,带身份证 brief
是一个标准 logging.Formatter
具有指定格式字符串的实例。第二个,带身份证 default
,具有更长的格式并显式定义时间格式,并且将导致 logging.Formatter
用这两个格式字符串初始化。以python源代码形式显示, brief
和 default
格式化程序具有配置子字典::
{
'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)
钥匙 '()'
已用作特殊键,因为它不是有效的关键字参数名称,因此不会与调用中使用的关键字参数的名称冲突。这个 '()'
也可以用作相应值是可调用的助记符。
访问外部对象¶
例如,有时配置需要引用配置外部的对象 sys.stderr
. 如果配置dict是使用python代码构建的,那么这很简单,但是当通过文本文件(例如json、yaml)提供配置时会出现问题。在文本文件中,没有标准的方法来区分 sys.stderr
从文本字符串 'sys.stderr'
. 为了便于区分,配置系统在字符串值中查找特定的特殊前缀,并对它们进行特殊处理。例如,如果文本字符串 'ext://sys.stderr'
在配置中作为值提供,然后 ext://
将被剥离,剩余的值将使用正常的导入机制进行处理。
这种前缀的处理方式类似于协议处理:有一种通用机制来查找与正则表达式匹配的前缀。 ^(?P<prefix>[a-z]+)://(?P<suffix>.*)$
据此,如果 prefix
是公认的, suffix
以前缀相关的方式处理,处理结果将替换字符串值。如果不识别前缀,则字符串值将保持原样。
访问内部对象¶
除了外部对象之外,有时还需要在配置中引用对象。这将由配置系统隐式地为它所知道的事情完成。例如,字符串值 'DEBUG'
对于一个 level
在记录器或处理程序中,将自动转换为值 logging.DEBUG
和 handlers
, filters
和 formatter
条目将获取对象ID并解析为适当的目标对象。
但是,对于用户定义的对象(这些对象不为 logging
模块。例如,考虑 logging.handlers.MemoryHandler
,需要一个 target
参数,它是要委托给的另一个处理程序。由于系统已经知道这个类,那么在配置中,给定的 target
只需要相关目标处理程序的对象ID,系统将从该ID解析为处理程序。但是,如果用户定义了 my.package.MyHandler
它有一个 alternate
处理程序,配置系统将不知道 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: my_app@domain.tld
toaddrs:
- support_team@domain.tld
- dev_team@domain.tld
subject: Houston, we have a problem.
在配置中,字符串 'cfg://handlers'
会用键决定听写 handlers
字符串 'cfg://handlers.email
会用键决定听写 email
在 handlers
听写等等。弦 'cfg://handlers.email.toaddrs[1]
会下决心 'dev_team.domain.tld'
弦 'cfg://handlers.email.toaddrs[0]'
将解析为值 'support_team@domain.tld'
. 这个 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__()
函数进行导入。您可能希望用您自己的导入机制替换它:如果是这样,您可以替换 importer
的属性 DictConfigurator
或者它的超类 BaseConfigurator
类。但是,您需要小心,因为函数是通过描述符从类中访问的。如果使用可调用的python进行导入,并且希望在类级别而不是实例级别定义它,则需要用 staticmethod()
. 例如::
from importlib import import_module
from logging.config import BaseConfigurator
BaseConfigurator.importer = staticmethod(import_module)
你不需要封装 staticmethod()
如果要在配置器上设置可调用的导入 实例 .
配置文件格式¶
配置文件格式 fileConfig()
基于 configparser
功能。文件必须包含名为 [loggers]
, [handlers]
和 [formatters]
它按名称标识文件中定义的每种类型的实体。对于每个这样的实体,都有一个单独的部分来标识该实体的配置方式。因此,对于一个名为 log01
在 [loggers]
节,相关配置详细信息保存在节中。 [logger_log01]
. 类似地,一个处理程序调用 hand01
在 [handlers]
节的配置将保存在名为 [handler_hand01]
,而格式化程序调用 form01
在 [formatters]
节的配置将在名为 [formatter_form01]
. 必须在名为 [logger_root]
.
注解
这个 fileConfig()
API比 dictConfig()
并且不提供涵盖日志记录某些方面的功能。例如,您不能配置 Filter
对象,用于过滤简单整数级以外的消息,使用 fileConfig()
. 如果您需要 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, CRITICAL
或 NOTSET
. 仅对于根记录器, NOTSET
表示将记录所有消息。级别值为 eval()
在 logging
包的命名空间。
这个 handlers
条目是处理程序名称的逗号分隔列表,必须出现在 [handlers]
部分。这些名称必须出现在 [handlers]
并在配置文件中具有相应的节。
对于根记录器以外的记录器,需要一些附加信息。下面的例子说明了这一点。
[logger_parser]
level=DEBUG
handlers=hand01
propagate=1
qualname=compiler.parser
这个 level
和 handlers
条目被解释为根记录器,除非非根记录器的级别被指定为 NOTSET
,系统向更高层次的记录器查询,以确定记录器的有效级别。这个 propagate
条目设置为1表示消息必须传播到此记录器的更高层次结构上的处理程序,或0表示消息 not 传播到层次结构上的处理程序。这个 qualname
条目是记录器的层次通道名称,也就是说应用程序用于获取记录器的名称。
下面举例说明了指定处理程序配置的部分。
[handler_hand01]
class=StreamHandler
level=NOTSET
formatter=form01
args=(sys.stdout,)
这个 class
条目指示处理程序的类(由 eval()
在 logging
包的命名空间)。这个 level
解释为记录员,以及 NOTSET
意思是“记录一切”。
这个 formatter
条目指示此处理程序的格式化程序的键名。如果为空,则为默认格式设置工具 (logging._defaultFormatter
)。如果指定了名称,它必须出现在 [formatters]
并在配置文件中具有相应的节。
这个 args
进入时 eval()
在 logging
包的命名空间是处理程序类的构造函数的参数列表。请参阅相关处理程序的构造函数或下面的示例,以了解如何构造典型条目。如果未提供,则默认为 ()
.
可选的 kwargs
进入时 eval()
在 logging
包的命名空间是处理程序类的构造函数的关键字参数dict。如果未提供,则默认为 {{}}
.
[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
datefmt=
style='%'
validate=True
class=logging.Formatter
格式化程序配置的参数与字典架构中的键相同 formatters section 。
参见
- 模块
logging
日志模块的API引用。
- 模块
logging.handlers
日志模块中包含有用的处理程序。