data = pickle.dumps(record_attr_dict, 1)
datalen = struct.pack('>L', len(data))
return datalen + data
请注意封存操作不是绝对安全的。 如果你关心安全问题,你可能会想要重写此方法以实现更安全的机制。 例如,你可以使用 HMAC 对封存对象进行签名然后在接收端验证它们,或者你也可以在接收端禁用全局对象的解封操作。
createSocket()
尝试创建一个套接字;失败时将使用指数化回退算法处理。 在失败初次发生时,处理程序将丢弃它正尝试发送的消息。 当后续消息交由同一实例处理时,它将不会尝试连接直到经过一段时间以后。 默认形参设置为初始延迟一秒,如果在延迟之后连接仍然无法建立,处理程序将每次把延迟翻倍直至达到 30 秒的最大值。
此行为由下列处理程序属性控制:
retryStart
(初始延迟,默认为 1.0 秒)。
retryFactor
(倍数,默认为 2.0)。
retryMax
(最大延迟,默认为 30.0 秒)。
这意味着如果远程监听器在处理程序被使用 之后 启动,你可能会丢失消息(因为处理程序在延迟结束之前甚至不会尝试连接,而在延迟期间静默地丢弃消息)。
DatagramHandler
DatagramHandler
类位于 logging.handlers
模块,它继承自 SocketHandler
,支持通过 UDP 套接字发送日志记录消息。
class logging.handlers.DatagramHandler(host, port)
返回一个 DatagramHandler
类的新实例,该实例旨在与使用 host 与 port 给定地址的远程主机进行通信。
由于 UDP 不是流式协议,在该处理器与 host 之前不存在持久连接。 因为这个原因,当使用网络套接字时,每当有事件被写入日志时都可能要进行 DNS 查询,这会给系统带来一些延迟。 如果这对你有影响,你可以自己执行查询并使用已查询到的 IP 地址而不是主机名来初始化这个处理器。
在 3.4 版的變更: 如果 port
指定为 None
,会使用 host
中的值来创建一个 Unix 域套接字 —— 在其他情况下,则会创建一个 UDP 套接字。
emit()
对记录的属性字典执行封存并以二进制格式将其写入套接字。 如果套接字存在错误,则静默地丢弃数据包。 要在接收端将记录解封并输出到 LogRecord
,请使用 makeLogRecord()
函数。
class logging.handlers.SysLogHandler(address=('localhost', SYSLOG_UDP_PORT), facility=LOG_USER, socktype=socket.SOCK_DGRAM)
返回一个 SysLogHandler
类的新实例用来与通过 address 以 (host, port)
元组形式给出地址的远程 Unix 机器进行通讯。 如果未指定 address,则使用 ('localhost', 514)
。 该地址会被用于打开套接字。 提供 (host, port)
元组的一种替代方式是提供字符串形式的地址,例如 '/dev/log'。 在这种情况下,会使用 Unix 域套接字将消息发送到 syslog。 如果未指定 facility,则使用 LOG_USER
。 打开的套接字类型取决于 socktype 参数,该参数的默认值为 socket.SOCK_DGRAM
即打开一个 UDP 套接字。 要打开一个 TCP 套接字(用来配合较新的 syslog 守护程序例如 rsyslog 使用),请指定值为 socket.SOCK_STREAM
。
请注意如果你的服务器不是在 UDP 端口 514 上进行侦听,则 SysLogHandler
可能无法正常工作。 在这种情况下,请检查你应当为域套接字所使用的地址 —— 它依赖于具体的系统。 例如,在 Linux 上通常为 '/dev/log' 而在 OS/X 上则为 '/var/run/syslog'。 你需要检查你的系统平台并使用适当的地址(如果你的应用程序需要在多个平台上运行则可能需要在运行时进行这样的检查)。 在 Windows 上,你大概必须要使用 UDP 选项。
在 macOS 12.x (Monterey) 上,Apple 修改了其 syslog 守护进程的行为 —— 它不再监听某个域套接字。 因此,你不能再预期 SysLogHandler
在此系统上有效。
请参阅 gh-91070 了解更多信息。
在 3.2 版的變更: 新增 socktype。
close()
关闭连接远程主机的套接字。
createSocket()
尝试创建一个套接字,如果它不是一个数据报套接字,则将其连接到另一端。 此方法会在处理器初始化期间被调用,但是如果此时另一端还没有监听则它不会被视为出错 —— 如果此时套接字还不存在,此方法将在发出事伯时再次被调用。
Added in version 3.11.
记录会被格式化,然后发送到 syslog 服务器。 如果存在异常信息,则它 不会 被发送到服务器。
在 3.2.1 版的變更: (参见: bpo-12168。) 在较早的版本中,发送至 syslog 守护程序的消息总是以一个 NUL 字节结束,因为守护程序的早期版本期望接收一个以 NUL 结束的消息 —— 即使它不包含于对应的规范说明 (RFC 5424)。 这些守护程序的较新版本不再期望接收 NUL 字节,如果其存在则会将其去除,而最新的守护程序(更紧密地遵循 RFC 5424)会将 NUL 字节作为消息的一部分传递出去。
为了在面对所有这些不同守护程序行为时能够更方便地处理 syslog 消息,通过使用类层级属性 append_nul
,添加 NUL 字节的操作已被作为可配置项。 该属性默认为 True
(保留现有行为) 但可在 SysLogHandler
实例上设为 False
以便让实例 不会 添加 NUL 结束符。
在 3.3 版的變更: (参见: bpo-12419。) 在较早的版本中,没有 "ident" 或 "tag" 前缀工具可以用来标识消息的来源。 现在则可以使用一个类层级属性来设置它,该属性默认为 ""
表示保留现有行为,但可在 SysLogHandler
实例上重写以便让实例不会为所处理的每条消息添加标识。 请注意所提供的标识必须为文本而非字节串,并且它会被原封不动地添加到消息中。
encodePriority(facility, priority)
将功能和优先级编码为一个整数。 你可以传入字符串或者整数 —— 如果传入的是字符串,则会使用内部的映射字典将其转换为整数。
符号 LOG_
的值在 SysLogHandler
中定义并且是 sys/syslog.h
头文件中所定义值的镜像。
名称(字符串)
alert
LOG_ALERT
crit
或 critical
LOG_CRIT
debug
LOG_DEBUG
emerg
或 panic
LOG_EMERG
err
或 error
LOG_ERR
LOG_INFO
notice
LOG_NOTICE
warn
或 warning
LOG_WARNING
名称(字符串)
LOG_AUTH
authpriv
LOG_AUTHPRIV
LOG_CRON
daemon
LOG_DAEMON
LOG_FTP
LOG_KERN
LOG_LPR
LOG_MAIL
LOG_NEWS
syslog
LOG_SYSLOG
LOG_USER
LOG_UUCP
local0
LOG_LOCAL0
local1
LOG_LOCAL1
local2
LOG_LOCAL2
local3
LOG_LOCAL3
local4
LOG_LOCAL4
local5
LOG_LOCAL5
local6
LOG_LOCAL6
local7
LOG_LOCAL7
NTEventLogHandler
NTEventLogHandler
类位于 logging.handlers
模块,它支持将日志记录消息发送到本地 Windows NT, Windows 2000 或 Windows XP 事件日志。 在你使用它之前,你需要安装 Mark Hammond 的 Python Win32 扩展。
class logging.handlers.NTEventLogHandler(appname, dllname=None, logtype='Application')
返回一个 NTEventLogHandler
类的新实例。 appname 用来定义出现在事件日志中的应用名称。 将使用此名称创建适当的注册表条目。 dllname 应当给出要包含在日志中的消息定义的 .dll 或 .exe 的完整限定路径名称(如未指定则会使用 'win32service.pyd'
—— 此文件随 Win32 扩展安装且包含一些基本的消息定义占位符。 请注意使用这些占位符将使你的事件日志变得很大,因为整个消息源都会被放入日志。 如果你希望有较小的日志,你必须自行传入包含你想要在事件日志中使用的消息定义的 .dll 或 .exe 名称)。 logtype 为 'Application'
, 'System'
或 'Security'
之一,且默认值为 'Application'
。
close()
这时,你就可以从注册表中移除作为事件日志条目来源的应用名称。 但是,如果你这样做,你将无法如你所预期的那样在事件日志查看器中看到这些事件 —— 它必须能访问注册表来获取 .dll 名称。 当前版本并不会这样做。
class logging.handlers.SMTPHandler(mailhost, fromaddr, toaddrs, subject, credentials=None, secure=None, timeout=1.0)
返回一个 SMTPHandler
类的新实例。 该实例使用电子邮件的发件人、收件人地址和主题行进行初始化。 toaddrs 应当为字符串列表。 要指定一个非标准 SMTP 端口,请使用 (host, port) 元组格式作为 mailhost 参数。 如果你使用一个字符串,则会使用标准 SMTP 端口。 如果你的 SMTP 服务器要求验证,你可以指定一个 (username, password) 元组作为 credentials 参数。
要指定使用安全协议 (TLS),请传入一个元组作为 secure 参数。 这将仅在提供了验证凭据时才能被使用。 元组应当或是一个空元组,或是一个包含密钥文件名的单值元组,或是一个包含密钥文件和证书文件的 2 值元组。 (此元组会被传给 smtplib.SMTP.starttls()
方法。)
可以使用 timeout 参数为与 SMTP 服务器的通信指定超时限制。
在 3.3 版的變更: 新增 timeout 參數。
emit(record)
对记录执行格式化并将其发送到指定的地址。
MemoryHandler
MemoryHandler
类位于 logging.handlers
模块,它支持在内存中缓冲日志记录,并定期将其刷新到 target 处理程序中。 刷新会在缓冲区满的时候,或是在遇到特定或更高严重程度事件的时候发生。
MemoryHandler
是更通用的 BufferingHandler
的子类,后者属于抽象类。 它会在内存中缓冲日志记录。 当每条记录被添加到缓冲区时,会通过调用 shouldFlush()
来检查缓冲区是否应当刷新。 如果应当刷新,则要使用 flush()
来执行刷新。
class logging.handlers.BufferingHandler(capacity)
使用指定容量的缓冲区初始化处理程序。 这里,capacity 是指缓冲的日志记录数量。
emit(record)
将记录添加到缓冲区。 如果 shouldFlush()
返回真值,则会调用 flush()
来处理缓冲区。
class logging.handlers.MemoryHandler(capacity, flushLevel=ERROR, target=None, flushOnClose=True)
返回一个 MemoryHandler
类的新实例。 该实例使用 capacity 指定的缓冲区大小(要缓冲的记录数量)来初始化。 如果 flushLevel 未指定,则使用 ERROR
。 如果未指定 target,则需要在此处理程序执行任何实际操作之前使用 setTarget()
来设置目标。 如果 flushOnClose 指定为 False
,则当处理程序被关闭时 不会 刷新缓冲区。 如果未指定或指定为 True
,则当处理程序被关闭时将会发生之前的缓冲区刷新行为。
在 3.6 版的變更: 新增 flushOnClose 參數。
close()
调用 flush()
,设置目标为 None
并清空缓冲区。
class logging.handlers.HTTPHandler(host, url, method='GET', secure=False, credentials=None, context=None)
返回一个 HTTPHandler
类的新实例。 host 可以为 host:port
的形式,如果你需要使用指定端口号的话。 如果没有指定 method,则会使用 GET
。 如果 secure 为真值,则将使用 HTTPS 连接。 context 形参可以设为一个 ssl.SSLContext
实例以配置用于 HTTPS 连接的 SSL 设置。 如果指定了 credentials,它应当为包含 userid 和 password 的二元组,该元组将被放入使用 Basic 验证的 HTTP 'Authorization' 标头中。 如果你指定了 credentials,你还应当指定 secure=True 这样你的 userid 和 password 就不会以明文在线路上传输。
在 3.5 版的變更: 新增 context 參數。
mapLogRecord(record)
基于 record
提供一个字典,它将被执行 URL 编码并发送至 Web 服务器。 默认实现仅返回 record.__dict__
。 在只需将 LogRecord
的某个子集发送至 Web 服务器,或者需要对发送至服务器的内容进行更多定制时可以重写此方法。
Added in version 3.2.
QueueHandler
类位于 logging.handlers
模块,它支持将日志记录消息发送到一个队列,例如在 queue
或 multiprocessing
模块中实现的队列。
配合 QueueListener
类使用,QueueHandler
可被用来使处理程序在与执行日志记录的线程不同的线程上完成工作。 这对 Web 应用程序以及其他服务于客户端的线程需要尽可能快地响应的服务应用程序来说很重要,任何潜在的慢速操作(例如通过 SMTPHandler
发送邮件)都要在单独的线程上完成。
class logging.handlers.QueueHandler(queue)
返回一个 QueueHandler
类的新实例。 该实例使用队列来初始化以向其发送消息。 queue 可以为任何队列类对象;它由 enqueue()
方法来使用,该方法需要知道如何向其发送消息。 队列 不要求 具有任务跟踪 API,这意味着你可以为 queue 使用 SimpleQueue
实例。
如果你在使用 multiprocessing
,则你应当避免使用 SimpleQueue
而要改用 multiprocessing.Queue
。
emit(record)
将准备 LogRecord 的结果排入队列。 如果发生了异常(例如由于有界队列已满),则会调用 handleError()
方法来处理错误。 这可能导致记录被静默地丢弃 (当 logging.raiseExceptions
为 False
时) 或者消息被打印到 sys.stderr
(当 logging.raiseExceptions
为 True
时)。
prepare(record)
准备用于队列的记录。 此方法返回的对象会被排入队列。
该基本实现会对记录进行格式化以合并消息、参数、异常和栈信息,如果它们存在的话。 它还会从记录中原地移除不可 pickle 的条目。 具体来说,它会用合并后的消息(通过调用处理器的 format()
方法获得)覆盖记录的 msg
和 message
属性,并将 args
, exc_info
和 exc_text
属性设置为 None
。
如果你想要将记录转换为 dict 或 JSON 字符串,或者发送记录被修改后的副本而让初始记录保持原样,则你可能会想要重写此方法。
该基本实现会使用这些参数对消息进行格式化,将 message
和 msg
属性设置为已格式化的消息并将 args
和 exc_text
属性设置为 None
以允许 pickle 操作并防止更多的格式化尝试。 这意味着 QueueListener
一方的处理器将没有自定义格式化所需的信息,例如异常信息等。 你可能会想要子类化 QueueHandler
并重写此方法以便避免将 exc_text
设置为 None
。 请注意对 message
/ msg
/ args
的改变与确保记录可以 pickle 是相关联的,根据你的 args
是否可以 pickle 你将可能或不可能避免这样做。 (请注意你可能必须不仅要考虑你自己的代码还要考虑你所使用的任何库中的代码。)
Added in version 3.2.
QueueListener
类位于 logging.handlers
模块,它支持从一个队列接收日志记录消息,例如在 queue
或 multiprocessing
模块中实现的队列。 消息是在内部线程中从队列接收并在同一线程上传递到一个或多个处理程序进行处理的。 尽管 QueueListener
本身并不是一个处理程序,但由于它要与 QueueHandler
配合工作,因此也在此处介绍。
配合 QueueHandler
类使用,QueueListener
可被用来使处理程序在与执行日志记录的线程不同的线程上完成工作。 这对 Web 应用程序以及其他服务于客户端的线程需要尽可能快地响应的服务应用程序来说很重要,任何潜在的慢速动作(例如通过 SMTPHandler
发送邮件)都要在单独的线程上完成。
class logging.handlers.QueueListener(queue, *handlers, respect_handler_level=False)
返回一个 QueueListener
类的新实例。 该实例初始化时要传入一个队列以向其发送消息,还要传入一个处理程序列表用来处理放置在队列中的条目。 队列可以是任何队列类对象;它会被原样传给 dequeue()
方法,该方法需要知道如何从其获取消息。 队列 不要求 具有任务跟踪 API(但如提供则会使用它),这意味着你可以为 queue 使用 SimpleQueue
实例。
如果你在使用 multiprocessing
,则你应当避免使用 SimpleQueue
而要改用 multiprocessing.Queue
。
如果 respect_handler_level
为 True
,则在决定是否将消息传递给处理程序之前会遵循处理程序的级别(与消息的级别进行比较);在其他情况下,其行为与之前的 Python 版本一致 —— 总是将每条消息传递给每个处理程序。
在 3.5 版的變更: 新增 respect_handler_level
引數。
dequeue(block)
从队列移出一条记录并将其返回,可以选择阻塞。
基本实现使用 get()
。 如果你想要使用超时设置或自定义的队列实现,则你可能会想要重写此方法。
enqueue_sentinel()
将一个标记写入队列以通知监听器退出。 此实现会使用 put_nowait()
。 如果你想要使得超时设置或自定义的队列实现,则你可能会想要重写此方法。
Added in version 3.3.
2001-2024, Python Software Foundation.
This page is licensed under the Python Software Foundation License Version 2.
Examples, recipes, and other code in the documentation are additionally licensed under the Zero Clause BSD License.
See History and License for more information.