15.9. logging.handlers — 日志handler

源码: Lib/logging/handlers.py


模块本身提供以下几个有用的handler。注意这三个handler(StreamHandler, FileHandlerNullHandler)实际上定义于logging模块本身中,只是将它们三个和其他handler的文档放在一起。

15.9.1. StreamHandler

StreamHandler类,位于logging模块中,能将日志输出发送至sys.stdout, sys.stderr等这样的流对象,或者任何的类文件对象(更准确的说,支持write()flush()方法的对象)。

class logging.StreamHandler(stream=None)

返回类StreamHandler的实例。如果指明了stream,该实例被用作日志输出; 否则使用sys.stderr

emit(record)

如果指明了formatter,它将用来格式化记录。然后记录被写到流中,以新行结尾。如果有异常信息,使用traceback.print_exception()来格式化它,结果加到流中。

flush()

调用flush()方法来刷新流。注意close()方法继承自Handler且不会有输出,所以需要时不时的调用flush()

15.9.2. FileHandler

FileHandler类位于核心logging包,将日志输出发送至磁盘文件。它从StreamHandler中继承输出的功能。

class logging.FileHandler(filename, mode='a', encoding=None, delay=False)

返回FileHandler类的实例。指明的文件会被打开,并用作日志流。如果没有指明mode,使用'a'如果encoding不为None,会用指定的编码来打开文件。如果delay为真,只到第一次调用emit()的时候才打开文件。默认情况下,文件会一直增长。

改变于版本2.6:添加了delay

close()

关闭文件。

emit(record)

将记录输出至文件。

15.9.3. NullHandler

新增于版本2.7。

NullHandler类位于核心logging包,不做任何的格式化或者输出。本质上它是个‘什么都不做’的handler,由库开发者使用。

class logging.NullHandler

返回NullHandler类的实例。

emit(record)

该方法不做任何事。

handle(record)

该方法不做任何事。

createLock()

对于锁该方法返回None,因为没有底层I/O,对其访问也不需要同步。

参见为库配置日志以了解如何使用NullHandler的更多信息。

15.9.4. WatchedFileHandler

新增于版本2.6。

WatchedFileHandler类位于logging.handlers模块,是个FileHandler,它可以观察用于记日志的文件。如果文件有改变,它关闭然后重新打开文件名。

文件发生变化可以是因为使用了newsysloglogrotate这样的程序,它们用来完成日志文件的循环。该handler主要用于Unix/Linux下,用来观察从上次修改后文件是否有变化。(如果文件的设备或者inode发生了变化,则文件被认为发生了变化。)如果文件发生了变化,关闭老的文件流,打开的文件得到一个新的文件流。

该handler不适用于Windows下,因为在Windows下打开的日志文件不能被移动或者重命名——日志以排外锁的方式打开文件——所以也就不需要这样的handler。进一步,Windows不支持ST_INO对于该值stat()永远返回0。

class logging.handlers.WatchedFileHandler(filename[, mode[, encoding[, delay]]])

返回WatchedFileHandler类的实例。指明的文件被打开,并用作日志流。如果没有指明mode,使用'a'如果encoding不为None,会用指定的编码来打开文件。如果delay为真,只到第一次调用emit()的时候才打开文件。默认情况下,文件会一直增长。

emit(record)

将记录输出至文件,但在此之前先检查文件是否有变化。如果文件有变化,在输出记录到文件之前先刷新当前流,然后关闭当前流,然后重新打开文件。

15.9.5. RotatingFileHandler

RotatingFileHandler类位于logging.handlers模块,支持磁盘日志文件的循环。

class logging.handlers.RotatingFileHandler(filename, mode='a', maxBytes=0, backupCount=0, encoding=None, delay=0)

返回RotatingFileHandler类的实例。指明的文件被打开,并被用作日志流。如果没有指明mode,使用'a'如果encoding不为None,使用指定的编码来打开文件。如果delay为真,只到第一次调用emit()的时候才打开文件。默认情况下,文件会一直增长。

可以使用maxBytesbackupCount 来让文件在预定义的尺寸发生翻转当文件大小大概要超出时,文件被关闭,新文件被打开用来输出。当文件大小接近于maxBytes长度时,翻转会发生;如果maxBytes为0,翻转永不发生。如果backupCount不为0,系统将保存老的日志文件,在文件名后加上‘.1’, ‘.2’这样的扩展名。例如如果backupCount是5,基本的文件名是app.log,将会得到app.log, app.log.1, app.log.2app.log.5总是写到文件app.log中。当文件被填满,文件被关闭并重命名为app.log.1,而已存的app.log.1, app.log.2等文件被重命名为app.log.2, app.log.3等。

改变于版本2.6:新增了delay

doRollover()

如上所述做文件的翻转。

emit(record)

输出记录到文件,负责文件的翻转。

15.9.6. TimedRotatingFileHandler

TimedRotatingFileHandler类位于logging.handlers模块,支持磁盘日志文件在特定的时间间隔发生循环。

class logging.handlers.TimedRotatingFileHandler(filename, when='h', interval=1, backupCount=0, encoding=None, delay=False, utc=False)

返回TimedRotatingFileHandler类的实例。 指明的文件被打开,并用作日志流。在循环时它也会设置文件后缀。循环发生基于wheninterval的乘积。

使用when来指明interval的类型。可能的值列在下面。注意大小写不敏感。

Value Type of interval
'S' Seconds
'M' Minutes
'H' Hours
'D' Days
'W0'-'W6' Weekday (0=Monday)
'midnight' Roll over at midnight

注意在使用基于工作日的循环时,‘W0’表示星期一,‘W1’表示星期二,依此类推,‘W6’表示星期日。这种情况下不使用interval

系统会保存老的日志文件,在文件名后添加扩展名。扩展名基于日期和时间,根据翻转间隔,使用strftime格式%Y-%m-%d_%H-%M-%S,或者其前面一部分。

第一次计算下一次翻转时间的时候(创建handler时),要么使用已存文件的上一次修改时间,要么使用当前时间。

如果utc为真,使用UTC时间;否则使用本地时间。

如果backupCount不为0,最多保留backupCount个文件,如果产生更多的文件,最老的文件会被删除。删除逻辑使用间隔来决定删除哪些文件,所以改变间隔可能会导致老的文件被保留。

如果delay为真,只到第一次调用emit()时文件才被打开。

改变于版本2.6:新增了delayutc

doRollover()

如上所述做文件的翻转。

emit(record)

输出记录到文件,负责文件的翻转。

15.9.7. SocketHandler

SocketHandler类位于logging.handlers模块,将日志输出发送至网络套接字。基类使用TCP套接字。

class logging.handlers.SocketHandler(host, port)

返回SocketHandler类的实例,用于和远端机器通信,远端机器的地址为hostport

close()

关闭套接字。

emit()

序列化记录的属性字典,以二进制格式写入套接字。如果套接字发生错误,静默丢弃包。如果连接断开,重建连接。使用makeLogRecord()函数在接受端反序列化记录为LogRecord

handleError()

处理emit()时发生的错误。极有可能时连接断开。关闭套接字这样可以在下个事件时重试。

makeSocket()

工厂方法,允许子类定义其希望的套接字类型。默认实现创建一个TCP套接字(socket.SOCK_STREAM)。

makePickle(record)

以二进制格式序列化记录的属性字典,带上长度前缀,返回值可以用于套接字传输。

注意序列化并不完全。如果关心安全,可以重写该方法以实现一个更安全的机制。例如,可以使用HMAC来签名序列化结果,并在接受端验证签名;或者可以在接受端禁止全局对象的反序列化。

send(packet)

将序列化的串packet发往套接字。该函数使得网络繁忙时可以发送部分包。

createSocket()

尝试创建套接字;失败时,使用指数回退算法。当第一次失败时,handler会丢弃要发送的消息。当接下来的消息由同一个的实例来处理时,不会马上尝试重连,而是先等一段时间。初始延迟的默认值是1秒,如果还是不能重连,加倍延迟时间,只到最大值30秒为止。

该行为由下列handler属性来控制:

  • retryStart (初始延迟,默认值为1.0秒)。
  • retryFactor (倍数,默认值为2.0)。
  • retryMax (最大延迟,默认值为30.0秒)。

这意味着如果在使用handler之后才启动远端监听者,有可能会丢失消息(因为handler不会在延迟之前尝试重连,而在这段时期会丢弃消息)。

15.9.8. DatagramHandler

DatagramHandler类位于logging.handlers模块,继承自SocketHandler,支持通过UDP套接字来发送日志消息。

class logging.handlers.DatagramHandler(host, port)

返回DatagramHandler类的实例,用于和远端机器通信,远端机器的地址为hostport

emit()

序列化记录的属性字典,以二进制格式写入套接字。如果套接字发生错误,静默丢弃包。使用makeLogRecord()函数在接受端反序列化记录为LogRecord

makeSocket()

重写工厂方法SocketHandler以创建UDP套接字(socket.SOCK_DGRAM)。

send(s)

向套接字发送序列化过的串。

15.9.9. SysLogHandler

SysLogHandler类位于logging.handlers模块,可以将日志消息发往远端或者本地的Unix syslog服务。

class logging.handlers.SysLogHandler(address=('localhost', SYSLOG_UDP_PORT), facility=LOG_USER, socktype=socket.SOCK_DGRAM)

返回SysLogHandler类的实例,用于和地址为address的远端Unix机器通信,地址为(host, port)这样的元组。如果不指明address,使用('localhost', 514)地址用于打开套接字。除了提供(host, port)元组,也可以给地址提供一个字符串,如‘/dev/log’。在这种情况下,使用Unix domain socket来将消息发送给syslog。如果不指明facility,使用LOG_USER打开的套接字类型取决于socktype参数,默认为socket.SOCK_DGRAM即UDP套接字。要打开一个TCP套接字(用于更新的syslog服务进程,如rsyslog),使用socket.SOCK_STREAM

注意如果服务器并不监听在UDP 514端口上,SysLogHandler可能不会工作。这种情况下,检查应该使用的domain socket的地址,它依赖于系统。例如,在Linux上一般是‘/dev/log’,在OS/X则是‘/var/run/syslog’。所以检查平台,使用合适的地址(如果应用需要跨平台,则要在运行时检查)。在Windows上不得不使用UDP选项。

改变于版本2.7:添加了socktype

close()

关闭到远端主机的套接字。

emit(record)

记录被格式化,然后发往syslog服务器。如果有异常信息,发往服务器。

encodePriority(facility, priority)

将设备和优先权编码为整数。可以传字符串或者整数——如果传了字符串,使用内部的映射字典来将其转成整数。

符号LOG_值定义于SysLogHandler,和sys/syslog.h头文件中定义的值一样。

优先权

Name (string) Symbolic value
alert LOG_ALERT
crit or critical LOG_CRIT
debug LOG_DEBUG
emerg or panic LOG_EMERG
err or error LOG_ERR
info LOG_INFO
notice LOG_NOTICE
warn or warning LOG_WARNING

设备

Name (string) Symbolic value
auth LOG_AUTH
authpriv LOG_AUTHPRIV
cron LOG_CRON
daemon LOG_DAEMON
ftp LOG_FTP
kern LOG_KERN
lpr LOG_LPR
mail LOG_MAIL
news LOG_NEWS
syslog LOG_SYSLOG
user LOG_USER
uucp 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
mapPriority(levelname)

将日志级别名映射成syslog优先权名字。重写该函数,如果使用了自定义级别,或者如果默认的算法不符合需求。默认算法将DEBUG, INFO, WARNING, ERRORCRITICAL 映射成对应的syslog名字,其它级别映射成‘warning’。

15.9.10. 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的名字。当前的版本不这样做。

emit(record)

决定消息ID,事件分类和类型,将消息记录到NT事件日志中。

getEventCategory(record)

返回记录的事件分类。如果需要指定自己的分类,重写该函数。该版本返回0。

getEventType(record)

返回记录的事件类型。如果需要指定自己的类型,重写该函数。该版本使用handler的typemap属性来做映射,该属性在__init__()被初始化成一个字典,包含了DEBUG, INFO, WARNING, ERRORCRITICAL的映射。如果使用了自定义级别,即可以重写该方法,也可以给handler的typemap属性合适的字典。

getMessageID(record)

返回记录的消息ID。如果使用自定义消息,可以给logger的msg传个ID而不是格式化字符串。然后可以使用字典查询来得到消息ID。该版本返回1,是win32service.pyd中的基本消息ID。

15.9.11. SMTPHandler

SMTPHandler类位于logging.handlers模块,可以经由SMTP将日志消息发往电子邮件地址。

class logging.handlers.SMTPHandler(mailhost, fromaddr, toaddrs, subject, credentials=None, secure=None)

返回SMTPHandler类的实例。实例由发信人/收信人地址及邮件的主题初始化得来。toaddrs是字符串的列表。要指明非标准SMTP端口,给mailhost参数一个(host, port)形式的元组。如果使用字符串,使用标准的SMTP端口。如果SMTP服务器需要验证,给credentials参数一个(username, password)元组。

要指明使用安全协议(TLS),给secure参数传个元组。这只有在验证凭证提供的情况下才使用。元组可以是空元组,或者单一值的元组,值为密钥文件的名字,或者是2值元组,值为密钥文件和证书文件的名字。(该元组被传给smtplib.SMTP.starttls()方法。

改变于版本2.6:添加了credentials

改变于版本2.7:添加了secure

emit(record)

格式化记录并将其发往指定的地址。

getSubject(record)

如果需要根据记录来指定主题,重写该方法。

15.9.12. MemoryHandler

MemoryHandler类位于logging.handlers模块,可以在内存中缓冲日志记录,周期性的将其刷往target handler。当缓冲满了会刷新,或者发现特定级别及其以上的事件也会刷新。

MemoryHandler是更通用的抽象类BufferingHandler的子类。它在内存中缓冲日志记录。每当记录被加到缓冲的时候,shouldFlush()被调用以检查是否需要刷新缓冲。如果需要,flush()被调用。

class logging.handlers.BufferingHandler(capacity)

初始化handler,建立指定capacity的缓冲。

emit(record)

向缓冲中添加记录。如果shouldFlush()返回真,调用flush()来处理缓冲。

flush()

重写该方法来实现自定义的刷新行为。该版本只是清空缓冲。

shouldFlush(record)

如果缓冲达到容量上限则返回真。可以重写该方法以实现自定义的刷新策略。

class logging.handlers.MemoryHandler(capacity, flushLevel=ERROR, target=None)

返回MemoryHandler类的实例。实例初始化大小为capacity的缓冲。如果未指明flushLevel,使用ERROR如果没有指明target,在handler能做任何有用的事情之前要使用setTarget()来设置目标。

close()

调用flush(),将目标设为None并清空缓冲。

flush()

对于MemoryHandler,刷新意味着如果有目标的话,将缓冲的记录发往目标。当该情况发生时缓冲也被清空。如果希望不同的行为,重写该方法。

setTarget(target)

为该handler设置目标handler。

shouldFlush(record)

检查缓冲是否满了,或者记录是否是flushLevel级别或者更高。

15.9.13. HTTPHandler

HTTPHandler类位于logging.handlers模块,可以将日志消息发往Web服务器,使用GET 或者 POST语义。

class logging.handlers.HTTPHandler(host, url, method='GET')

返回HTTPHandler类的实例。如果需要特定的端口号的话,host可以是host:port

mapLogRecord(record)

基于record提供一个字典,记录将会被URL编码并发送到web服务器。默认实现是返回record.__dict__如果只是LogRecord的子集会被发往web服务器,或者需要控制特定的记录被发往web服务器,重写该方法。

emit(record)

将记录以URL编码的字典的方式发送到Web服务器。mapLogRecord()方法用来做转化。

注意

准备记录将其发送到Web服务器不同于一般的格式化操作,使用setFormatter()HTTPHandler指定Formatter没有效果。它不是调用format(),而是调用mapLogRecord()然后是urllib.urlencode()来将字典编码成适合发送到Web服务器的形式。

参见

logging模块
日志模块的API参考。
logging.config模块
日志模块的配置API。