16.6. logging
- Python的日志记录¶
该模块定义的函数和类为应用程序和库实现了一个灵活的事件日志系统。
由标准库模块提供日志记录API的关键好处是所有的Python模块都可以使用日志,因此你的应用程序的日志可以将你自己的信息与第三方模块的信息包含在一起集成起来。
该模块提供许多的功能和灵活性。如果你还不熟悉日志,掌握它的最好的办法是阅读它的教程(参考右边的链接)。
下面列出该模块定义的基本类以及它们的函数。
- Loggers 提供应用程序代码直接使用的接口。
- Handlers 发送日志记录(由loggers创建)到正确的目标。
- Filters 提供粒度更好的工具用于决定输出哪些日志记录。
- Formatters 指出最终输出中的日志记录的格式。
16.6.1. Logger Objects¶
Loggers 具有以下的属性和方法。Logger对象一般不会直接实例化得到,而是通过模块级别的函数logging.getLogger(name)
得到。以相同的名称多次调用getLogger()
将永远返回相同Logger对象的引用。
name
可以是一个以句号分隔的层次结构的值,比如foo.bar.baz
(它也可以只是普通的foo
)。层次列表下游的loggers是上游loggers的子孙。例如,对于给定的一个logger对象 foo
,其它logger对象foo.bar
, foo.bar.baz
, foo.bam
,它们都是foo
的子辈。logger对象名字的层级和python包的层级是相似的,并且如果你使用推荐的结构logging.getLogger(__name__)
来管理你的loggers对象的话,那就与python包的层级结构是一模一样的。因为在一个模块中__name__
是一个在python包中名字空间的模块的名称。
- class
logging.
Logger
¶
-
Logger.
propagate
¶ 如果它为真,记录到该logger的事件除了传递给该logger的handler之外,也被传递给上游(祖先)logger的handler。信息将直接传递给祖先logger的handler - 不会考虑祖先logger的级别和filter。
如果它为假,日志消息不会传递给祖先loggers的handlers。
构造函数设置该属性为
True
。注
如果你添加一个handler到logger和 它的一个或多个祖先中,它可能多次打印相同的记录。一般来说,你不应该需要将一个handler添加给多个logger - 如果你只将它添加到合适的logger而它是logger层次中最高的,那么它将看到所有子logger记录的事件,只要它们的propagate设置保留为
True
。一个常见的场景是将handlers附加给根logger,然后让propagation负责剩下的事情。
-
Logger.
setLevel
(lvl)¶ 设置该logger的级别为lvl。严重程度低于lvl 的日志消息将被忽略。当创建一个logger时,它的级别设置为
NOTSET
(它使得当该logger是根logger时所有的信息都将被处理,或者当该logger不是根logger时委托给父logger)。注意根logger以级别WARNING
创建。“委托给父logger”的意思是如果logger的级别是NOTSET,将遍历它的祖先链直到找到一个级别不是NOTSET的祖先或者到达根logger。
如果找到级别不是NOTSET的祖先,祖先的级别被认为是开始查找祖先的logger的有效级别,用来决定如何处理日志事件。
如果到达root且它的级别是NOTSET,那么将处理所有的信息。否则root的级别将用作有效的级别。
级别的列表参见Logging Levels。
在版本3.2中更改: lvl参数现在接受级别的字符串表示形式,如“INFO”,作为整数常量的替代,如
INFO
然而,注意,级别在内部存储为整数,并且方法例如getEffectiveLevel()
和isEnabledFor()
将返回/期望被传递的整数。
-
Logger.
isEnabledFor
(lvl)¶ 表明lvl 级别的信息是否会被该logger处理。该方法首先检查由
logging.disable(lvl)
设置的模块级的级别,然后检查由getEffectiveLevel()
决定的该logger的有效级别。
-
Logger.
getEffectiveLevel
()¶ 表明该logger的有效级别。如果使用
setLevel()
设置了非NOTSET
的级别,该级别被返回。否则,将向根向前遍历层次结构,直到找到除NOTSET
之外的值,并返回该值。返回的值是一个整数,通常为logging.DEBUG
,logging.INFO
等。
-
Logger.
getChild
(suffix)¶ 返回该logger的由suffix决定的后代logger。
logging.getLogger('abc').getChild('def.ghi')
返回的logger和logging.getLogger('abc.def.ghi')
返回的logger是同一个。这是一个方便的方法,当父记录器使用例如__ name __
而不是字面值字符串。版本3.2中的新功能。
-
Logger.
debug
(msg, *args, **kwargs)¶ 在logger上记录一条级别为
DEBUG
的消息。msg为消息格式字符串,args为通过字符串格式操作符合并到msg的参数。(注意这意味着可以在格式字符串中使用关键字和一个字典参数。)在kwargs中有三个关键字参数,它们被检查:exc_info,stack_info和extra。
如果exc_info不计算为假,则会导致将异常信息添加到日志记录消息中。如果提供了异常元组(以
sys.exc_info()
返回的格式)或异常实例,则使用它;否则,调用sys.exc_info()
以获取异常信息。第二个可选的关键字参数是stack_info,默认为
False
。如果为true,则将堆栈信息添加到日志记录消息中,包括实际的日志调用。注意,这不是通过指定exc_info显示的堆栈信息:前者是从堆栈底部到当前线程中的日志调用的堆栈帧,而后者是有关堆栈帧,它们在寻找异常处理程序时例外之后被解开。您可以独立于exc_info指定stack_info,例如只是展示你如何到达代码中的某一点,即使没有引发异常。堆栈帧打印在标题行后面,说:
Stack (most recent call last):
这模拟了
跟踪 (最近 最近 调用 ): / t0>在显示异常帧时使用。
第三个关键字参数是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地址和已认证用户名)。在这种环境下,很可能对特殊的
Handler
使用特定的Formatter
。版本3.2中的新功能:添加了stack_info参数。
在版本3.5中已更改: exc_info参数现在可以接受异常实例。
-
Logger.
warning
(msg, *args, **kwargs)¶ 在该logger上以
WARNING
级别记录一条信息。其参数的解释与debug()
相同。注
有一个过时的方法
warn
,其功能与warning
相同。由于warn
已弃用,请不要使用它 - 请改用warning
。
-
Logger.
exception
(msg, *args, **kwargs)¶ 在该logger上以
ERROR
级别记录一条信息。其参数的解释与debug()
相同。异常信息将添加到日志信息中。该方法应该只在异常处理器调用。
-
Logger.
addFilter
(filt)¶ 添加指定的filter filt 到该logger。
-
Logger.
removeFilter
(filt)¶ 删除该logger中的filter filt。
-
Logger.
filter
(record)¶ 对record应用该logger的filters,如果该record应该被处理,返回真。轮流调用filters,直到有一个返回假。如果没有filter返回假值,该record将会被处理(传递给handlers)。如果有一个返回了假值,将不会对record做进一步的处理。
-
Logger.
addHandler
(hdlr)¶ 将指定的handlerhdlr添加到logger中。
-
Logger.
removeHandler
(hdlr)¶ 从logger中移除指定的handler hdlr。
-
Logger.
findCaller
(stack_info=False)¶ 查找调用者的源码文件名和行号。将文件名,行号,函数名和堆栈信息作为4元素元组返回。除非stack_info为True,否则堆栈信息将作为无返回。
-
Logger.
handle
(record)¶ 处理一个record,将它传给该logger及其祖先的所有的handler(直到propagate为假为止)。该方法用于从套接字接收到的反序列化的record,以及那些本地创建的。使用
filter()
日志级别过滤会应用。
-
Logger.
makeRecord
(name, lvl, fn, lno, msg, args, exc_info, func=None, extra=None, sinfo=None)¶ 这是一个工厂方法,可以在子类中覆盖它来创建特定的
LogRecord
实例。
-
Logger.
hasHandlers
()¶ 检查此记录器是否已配置任何处理程序。这是通过在记录器层次结构中查找此记录器及其父节点中的处理程序来完成的。如果找到处理程序,则返回
True
,否则False
。当找到具有“propagate”属性设置为False的记录器时,该方法停止搜索层次结构 - 这将是检查处理程序是否存在的最后一个记录器。版本3.2中的新功能。
16.6.2. Logging Levels¶
下表给出日志级别的数值。这主要在你想定义自己的级别时有用,且自定义级别的值是相对于预定义级别的值。如果定义具有相同数值的级别,它将覆盖预定义值;预定义的名称将丢失。
级别 | 数值 |
---|---|
CRITICAL | 50 |
ERROR | 40 |
WARNING | 30 |
INFO | 20 |
DEBUG | 10 |
NOTSET | 0 |
16.6.3. Handler Objects¶
Handler有以下属性和方法。注意:Handler
不应该直接被实例化,此类应该作为基类来子类化出一些有用的类。然而,__init__()
方法在子类中需要被Handler.__init__()
来调用。
-
Handler.
__init__
(level=NOTSET)¶ 初始化
Handler
实例,设置它的级别,设置filter列表为空列表,创建锁(使用createLock()
)用以序列化访问I/O机制。
-
Handler.
createLock
()¶ 初始化线程锁,用以序列化访问底层的可能非线程安全的I/O机制,
-
Handler.
acquire
()¶ 获取
createLock()
创建的线程锁。
-
Handler.
setLevel
(lvl)¶ 设置handler级别为lvl。严重程度低于lvl 的日志消息将被忽略。当handler创建时,级别设为
NOTSET
(这会处理所有消息)。级别的列表参见Logging Levels。
在版本3.2中更改: lvl参数现在接受级别的字符串表示形式,如“INFO”,作为整数常量的替代,如
INFO
。
-
Handler.
addFilter
(filt)¶ 添加指定的filterfilt到handler。
-
Handler.
removeFilter
(filt)¶ 从handler移除指定的filter filt。
-
Handler.
filter
(record)¶ 将handler的filter应用到record,如果该record应该被处理,返回真。轮流调用filters,直到有一个返回假。如果没有一个filter返回假,发出该record。如果有一个filter返回假,handler将不会发出record。
-
Handler.
flush
()¶ 确保所有的日志输出被刷新。基类版本不做任何事情,留给子类来实现。
-
Handler.
close
()¶ 清除handler所使用的资源。该版本没有输出,它将handler从内部handler列表中移除,当调用
shutdown()
时handler列表中的handler都会被关闭。子类应该保证在重写的close()
方法中调用此方法。
-
Handler.
handle
(record)¶ 依赖于加到该handler的filter,有条件的发出特定的日志record。它包装了发出record时对I/O线程锁的获取/释放过程。
-
Handler.
handleError
(record)¶ 此方法应该在调用
emit()
时遇到异常后从handlers被调用。如果模块级属性raiseExceptions
为False
,异常会被静默忽略掉。这是日志系统常见的行为——大多数用户并不关心日志系统中的错误,他们只关心应用的错误。当然如果你愿意,你可以用自定义的处理器来替换它。record参数是异常发生时正在处理的record。(raiseExceptions
的默认值为True
,这在开发中很有用)。
-
Handler.
format
(record)¶ 格式化record,如果有formatter,使用formatter。否则使用模块默认的formatter。
-
Handler.
emit
(record)¶ 做记录日志record真正需要的动作。基类版本抛出
NotImplementedError
,留给子类来实现。
参见logging.handlers
以了解标准库中的handler。
16.6.4. Formatter Objects¶
Formatter
对象有以下属性和方法。它负责将LogRecord
转换(通常)成人类和其它系统可以理解的字符串。基类Formatter
允许指定某个格式的字符串。如果提供None,那么'%(message)s'
将会作为默认值,它仅仅包括日志调用中的信息。如果想加入一些额外的格式输出(例如时间戳)信息项,请继续阅读下去。
Formatter对象可以用一个使LogRecord
的属性的反应信息有用的字符串来进行实例化。例如上面提到的用来使用户信息和参数预格式化进LogRecord
对象的 message属性有效的默认值。格式化字符串包含标准的Python的%-风格的映射键值。欲了解更多关于字符串格式化的信息,请参见printf-style String Formatting。
在LogRecord
对象中,有效的映射键存在于LogRecord attributes属性中。
- class
logging.
Formatter
(fmt=None, datefmt=None, style='%')¶ 返回一个
Formatter
类的新实例。实例以整个消息的格式化字符串以及消息中日期/时间部分的格式化字符串来初始化。如果fmt不被指定,'%(message)s'
将会被使用。如果不指明datefmt,将使用ISO8601日期格式。style可以是 ‘%’, ‘{‘ or ‘$’中的任何一个,并且它决定格式化字符串将会怎样与它的数据融合: 使用%格式化的更多信息参考
str.format()
orstring.Template
.有关使用{ - 和$ - 格式化日志消息的详细信息,请参阅在应用程序中使用特定格式样式。在版本3.2中已更改:添加了样式参数。
-
format
(record)¶ 记录的属性字典被用作字符格式化操作的参数。返回结果字符串。在格式化字典之前将会执行一些准备性的动作。记录的message属性用msg % args来计算。如果格式化字符串包含
'(asctime)'
,formatTime()
将会被调用用以格式化事件的时间。如果有异常信息,使用formatException()
来格式化它,并将结果附加到消息。注意格式化过的异常信息缓存于exc_text属性。这是有用的,因为异常信息可以被序列化并在网络上传递;但是如果你有多个Formatter
子类,每个子类都定制了异常信息的格式化方式,这种情况下就得注意。在这种情况下,在一个formatter完成了格式化操作之后需要清掉缓存的值,这样下一个formatter才会重新计算而不是使用缓存值。如果堆栈信息可用,它将附加在异常信息之后,使用
formatStack()
在必要时对其进行转换。
-
formatTime
(record, datefmt=None)¶ 此方法应该被从想使用格式化时间的formatter对象的
format()
调用。可以在formatter中重写该方法以满足特定的需求,但基本行为如下:如果指明了datefmt字符串,用该字符串来调用time.strftime()
以格式化记录的创建时间。否则使用ISO8601格式。返回结果字符串。该函数使用用户配置的函数来将创建时间转成元组。默认情况下,使用
time.localtime()
;为特定格式化程序更改此属性实例,将转换器
属性设置为具有与time.localtime()
或time.gmtime()
。如果需要对所有的formatter进行修改,例如你希望所有的日志时间都以GMT格式显式,可以设置converter
类的Formatter
属性。在版本3.3中更改:以前,默认的ISO 8601格式是硬编码的,如在此示例中:
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. Filter Objects¶
Filters
和Handlers
可以使用Loggers
来完成比级别更复杂的过滤。filter基类只允许特定logger层次以下的事件。例如,用“A.B”初始化的过滤器将允许由记录器“A.B”,“A.B.C”,“A.B.C.D”,“A.B.D”等记录的事件。但是,不接受“A.BB”,“B.A.B”等的格式。如果用空字符串来初始化,所有的事件都接受。
- class
logging.
Filter
(name='')¶ 返回
Filter
类的实例。如果指明了name,它是一个logger的名字,该logger及其子logger的事件运行通过该过滤器。如果name是空字符串,所有的事件都允许。-
filter
(record)¶ 特定的记录是否要记下来?0为否,非0为是。如果认为合适,该方法可以修改记录。
-
注意,在处理程序发出事件之前,请参考处理程序附带的过滤器,而记录事件时会查询附加到日志记录器的过滤器(使用debug()
,info
等。),然后将事件发送给处理程序。这意味着子logger产生的事件是不会被logger的filter设定所过滤掉的,除非filter也适用于子logger。
可以不必继承Filter
:只要实例有filter
方法,且拥有相同的语义即可。
在版本3.2中更改:您不需要创建专门的Filter
类,或使用其他类与filter
方法:函数(或其他可调用)作为过滤器。过滤逻辑将检查过滤器对象是否具有filter
属性:如果是,则假设它是Filter
及其filter()
否则,假定它是一个可调用的,并以该记录作为单个参数进行调用。返回的值应符合filter()
返回的值。
尽管filter主要用比级别更复杂的标准来过滤记录,但它能看到它所附于的handler或者logger所处理的所有记录:这可以做许多有用的事情,比如对特定的logger或者handler所处理的记录的计数;或者对正在处理的LogRecord,添加、修改或者移除属性。修改LogRecord需要小心,但是它可以在日志中注入上下文信息(参见Using Filters to impart contextual information)。
16.6.6. LogRecord Objects¶
每次某个事件被日志记录时LogRecord
实例就会被Logger
自动创建,并且可以被手动创建,通过 makeLogRecord()
(例如,一个网络序列化事件).
- class
logging.
LogRecord
(name, level, pathname, lineno, msg, args, exc_info, func=None, sinfo=None)¶ 包含所有跟记录的事件相关的信息。
主要信息由
msg
和args
传入,which are combined usingmsg % args
to create themessage
field of the record.Parameters: - name - 用于记录由此LogRecord表示的事件的记录器的名称。注意该名字不会变,哪怕它有可能是由一个不同的(父)logger的handler所发出来的。
- level - 记录事件的数字级别(DEBUG,INFO等之一)请注意,将其转换为LogRecord的两个属性:
levelno
表示数字值,levelname
表示相应的级别名称。 - pathname - 进行记录调用的源文件的完整路径名。
- lineno - 进行日志调用的源文件中的行号。
- msg - 事件描述消息,可能是带有变量数据占位符的格式字符串。
- args - 要合并到msg参数中的变量数据,以获取事件描述。
- exc_info - 当前异常信息的异常元组,如果没有异常信息,则为None。
- func - 调用日志记录调用的函数或方法的名称。
- sinfo - 表示当前线程中堆栈基址的堆栈信息的文本字符串,直到日志调用。
-
getMessage
()¶ LogRecord
实例在融合用户提供的参数后返回一条message。如果调用日志时用户提供的参数不是字符串,调用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 attributes¶
LogRecord有一些属性,大都源自于构造函数的参数。(注意名字在LogRecord构造函数参数中和LogRecord属性中并不总是对应的。)这些属性用来将数据从记录合并到格式化字符串中。下表列出了属性名(按名称排序),含义及其对应的%风格的格式字符串占位符。
如果使用{} -formatting(str.format()
),则可以使用{attrname}
作为格式字符串中的占位符。如果您使用$ -formatting(string.Template
),请使用形式$ {attrname}
。在这两种情况下,当然,将attrname
替换为要使用的实际属性名称。
在{}格式化的情况下,您可以通过将属性名称放在属性名称后面指定格式化标记,并用冒号分隔。例如:{msecs:03d}
的占位符会将4
的毫秒值格式化为004
。有关可用选项的完整详细信息,请参阅str.format()
文档。
属性名 | 格式 | 描述 |
---|---|---|
args | 不需要格式化args。 | 参数的元组合并到msg 中以产生message ,或者其值用于合并的字典(当只有一个参数时,它是字典)。 |
asctime | %(asctime)s | 创建LogRecord 时的可读时间。默认情况下,它的格式为'2003-07-08 16:49:45,896'(逗号后面的数字是毫秒部分的时间)。 |
创建 | %(created)f | LogRecord 创建的时间(形如time.time() 的返回值,即epoch跳秒)。 |
exc_info | 不需要格式化args。 | 异常元组(形如sys.exc_info ,如果没有异常为None。 |
文件名 | %(filename)s | pathname 的文件名部分。 |
funcName | %(funcName)s | 日志调用所在的函数名。 |
levelname | %(levelname)s | 消息的级别名称('DEBUG' , 'INFO' , 'WARNING' , 'ERROR' , 'CRITICAL' )。 |
levelno | %(levelno)s | 消息的级别数字(DEBUG , INFO , WARNING , ERROR , CRITICAL )。 |
行号 | %(lineno)d | 日志调用所在的源码行号(如果可用)。 |
模块 | %(module)s | 模块(filename 的名字部分)。 |
毫秒 | %(msecs)d | LogRecord 创建时间中的毫秒部分。 |
信息 | %(message)s | The logged message, computed as msg % args . 当调用Formatter.format() 时设置。 |
msg | 不需要格式化args。 | 在原始日志调用中传递的格式字符串。与args 合并以产生message 或任意对象(请参阅Using arbitrary objects as messages)。 |
名称 | %(name)s | 记录日志的logger的名字。 |
路径名 | %(pathname)s | 日志调用所在文件的完整路径名(如果可用)。 |
处理 | %(process)d | 进程 ID (如果可用)。 |
processName | %(processName)s | 进程名(如果可用)。 |
relativeCreated | %(relativeCreated)d | LogRecord创建时离装载日志模块时的毫秒数。 |
stack_info | 不需要格式化args。 | 堆栈帧信息(如果可用)从当前线程中堆栈的底部,直到并包括记录调用的堆栈帧,导致创建此记录。 |
线 | %(thread)d | 线程 ID (如果可用)。 |
threadName | %(threadName)s | 线程名字(如果可用)。 |
在版本3.1中已更改: 已添加processName。
16.6.8. LoggerAdapter Objects¶
LoggerAdapter
实例用来方便的传递文本信息给logging调用。使用的例子可以参见adding contextual information to your logging output。
- class
logging.
LoggerAdapter
(logger, extra)¶ 返回
LoggerAdapter
的实例,它以底层的Logger
实例和一个类字典对象来初始化。-
process
(msg, kwargs)¶ 修改传给日志调用的消息和/或关键字参数,以插入上下文信息。实现使用构造函数中的extra对象,使用'extra'键值将其加入kwargs。返回值是(msg, kwargs)的元组,是传入的参数的值(可能修改过)。
-
In addition to the above, LoggerAdapter
supports the following methods of Logger
: debug()
, info()
, warning()
, error()
, exception()
, critical()
, log()
, isEnabledFor()
, getEffectiveLevel()
, setLevel()
and hasHandlers()
. 这些方法具有与Logger
中的对应方相同的签名,因此您可以互换使用这两种类型的实例。
Changed in version 3.2: The isEnabledFor()
, getEffectiveLevel()
, setLevel()
and hasHandlers()
methods were added to LoggerAdapter
. 这些方法委托给底层的记录器。
16.6.9. Thread Safety¶
日志模块被设计成线程安全的,不需要客户端做什么特别的动作。它实现了这一点,虽然使用线程锁;有一个锁来串行访问模块的共享数据,并且每个处理程序还创建一个锁以串行化对其底层I / O的访问。
如果你使用signal
模块来实现异步信号处理器,你不能在处理器代码中使用日志。这是因为threading
模块中的锁实现并不总是可重入的,从而不能在异步信号处理器中被调用。
16.6.10. Module-Level Functions¶
除了上述类,还有一些模块级别的函数。
-
logging.
getLogger
(name=None)¶ 返回具有指定名称的记录器,如果名称为
无
,则返回一个记录器,它是层次结构的根记录器。如果指定,名称通常是点分隔的分层名称,如'a','a.b'或'a.b.c.d'。使用日志的开发者决定选择什么样的名字。以相同名字调用该函数总是返回同一个logger实例。这意味着logger实例不需要在应用的各个部分之间传来传去。
-
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)¶ 在根logger上记录一个
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):
这模拟了
跟踪 (最近 最近 调用 ): / t0>在显示异常帧时使用。
第三个可选的关键字参数是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地址和已认证用户名)。在这种环境下,很可能对特殊的
Handler
使用特定的Formatter
。版本3.2中的新功能:添加了stack_info参数。
-
logging.
warning
(msg, *args, **kwargs)¶ 在根logger上记录一个
WARNING
级别的消息。其参数的解释与debug()
相同。注
有一个过时的函数
warn
,其功能与warning
相同。由于warn
已弃用,请不要使用它 - 请改用warning
。
-
logging.
exception
(msg, *args, **kwargs)¶ 在根logger上记录一个
ERROR
级别的消息。其参数的解释与debug()
相同。异常信息将添加到日志信息中。该函数应该只在异常处理器中被调用。
-
logging.
log
(level, msg, *args, **kwargs)¶ 在根logger上记录一个级别为level的消息。其余参数的解释与
debug()
相同。注
上述模块级别的便利函数委托给根logger,调用
basicConfig()
保证至少有一个handler可用。因为如此,不应该在线程中调用这些函数,也不应该在Python 2.7.1 和 3.2之前的版本使用这些函数;除非在线程启动之前,至少有一个可用的handler被加到根logger。在早期版本的Python中,由于basicConfig()
有线程安全的问题,(在极少情况下)可能导致在根logger上多次添加handler,从而导致相同事件被记录多个消息。
-
logging.
disable
(lvl)¶ 对所有logger提供级别lvl,该级别会覆盖logger自己的级别。如果需要临时限制整个应用的日志输出,这个函数就很有用。它会禁用lvl及其以下级别的日志调用,如果禁用INFO,那么 INFO 和 DEBUG 事件将会被丢弃, WARNING 及其以上的事件会基于logger的有效级别来处理。如果调用
logging.disable(logging.NOTSET)
,它将有效地删除此覆盖级别,以便日志记录输出再次取决于单个记录器的有效级别。
-
logging.
addLevelName
(lvl, levelName)¶ 在内部字典中关联lvl和levelName文本,可以用来将一个数字级别映射到文本表示,比如
Formatter
在格式化消息的时候。可以用该函数来定义自己的级别。限制就是必须用该函数来登记所有的级别,级别应该是正整数,且随着严重程度的增加而递增。注
如果考虑定义自己的级别,请参见章节Custom Levels。
-
logging.
getLevelName
(lvl)¶ 返回日志级别lvl的文本表示。如果级别是预定义的
CRITICAL
,ERROR
,WARNING
,INFO
或DEBUG
中的一个,那么可以得到对应的字符串。如果通过addLevelName()
关联了级别名,那么关联到lvl的名字会返回。如果传入的是已定义的级别对应的数字值,返回相应的字符串表示。否则,将返回字符串'Level%s'%lvl。注
级别是内部整数(因为它们需要在日志记录逻辑中进行比较)。此函数用于通过
%(levelname)s
格式说明符(请参阅LogRecord attributes)在整数级别和格式化日志输出中显示的级别名称之间进行转换。 。在版本3.4中更改:在3.4之前的Python版本中,此函数也可以传递文本级别,并返回级别的相应数字值。这个未记录的行为被认为是一个错误,并在Python 3.4中删除,但恢复在3.4.2由于保留向后兼容性。
-
logging.
makeLogRecord
(attrdict)¶ 创建并返回
LogRecord
实例,attrdict定义了其属性。可以在网络上传输序列化过的LogRecord
属性字典,然后在接受端重建LogRecord
实例。
-
logging.
basicConfig
(**kwargs)¶ 创建一个带默认
StreamHandler
的Formatter
,将其加到根logger,从而配置基本的日志系统。函数debug()
,info()
,warning()
,error()
和critical()
在根looger没有handler的情况下会自动调用basicConfig()
。如果根logger已经配置了handler则该函数什么都不做。
注
该函数应该在其它线程启动之前,在主线程中被调用。在早于2.7.1 和 3.2的Python中,如果该函数在多线程中被调用,(在极少情况下)有可能一个handler被多次加到根logger,导致非预期的结果,比如日志中出现重复的消息。
支持下列关键字参数。
格式 描述 filename
创建一个FileHandler,使用指定的文件名,而不是使用StreamHandler。 filemode
如果指明了文件名,指明打开文件的模式(如果没有指明filemode,默认为'a')。 format
handler使用指明的格式化字符串。 datefmt
使用指明的日期/时间格式。 style
如果指定 format
,请将此样式用于格式字符串。One of ‘%’, ‘{‘ or ‘$’ for %-formatting,str.format()
orstring.Template
respectively, and defaulting to ‘%’ if not specified.level
指明根logger的级别。 stream
使用指明的流来初始化StreamHandler。请注意,此参数与“filename”不兼容 - 如果两者都存在,则会引发 ValueError
。handlers
如果指定,这应该是已经创建的处理程序添加到根记录器的迭代。任何没有格式化程序集的处理程序将被分配在此函数中创建的默认格式化程序。请注意,此参数与“filename”或“stream”不兼容 - 如果两者都存在,则会引发 ValueError
。在版本3.2中已更改:添加了
style
参数。在版本3.3中更改:添加了
handlers
参数。添加了额外的检查以捕获指定了不兼容参数的情况。handlers
与stream
或filename
或stream
以及filename
-
logging.
shutdown
()¶ 通知日志系统执行有序的关闭,刷新并关闭所有的handler。在应用退出的时候调用该函数,调用该函数后不应该继续使用日志系统。
-
logging.
setLoggerClass
(klass)¶ 告知日志系统使用class类来实例化logger。类要定义需要一个名字参数的
__init__()
,__init__()
应该调用Logger.__init__()
。典型的,如果应用使用自定义的logger行为,在初始化任一个logger之前需要调用该函数。
-
logging.
setLogRecordFactory
(factory)¶ 设置用于创建
LogRecord
的可调用项。Parameters: factory - 用于实例化日志记录的工厂调用。 版本3.2中的新功能:此函数已与
getLogRecordFactory()
一起提供,以允许开发人员更好地控制LogRecord
事件构建。工厂有以下声明:
工厂(名称, 级别, fn, lno, msg, args, exc_info, func = None, sinfo = None, ** kwargs) t10 >
name: The logger name. level: The logging level (numeric). fn: The full pathname of the file where the logging call was made. lno: The line number in the file where the logging call was made. msg: The logging message. args: The arguments for the logging message. exc_info: An exception tuple, or None. func: The name of the function or method which invoked the logging call. sinfo: A stack traceback such as is provided by traceback.print_stack()
, showing the call hierarchy.kwargs: Additional keyword arguments.
16.6.11. Module-Level Attributes¶
-
logging.
lastResort
¶ 通过此属性可以获得“最后手段的处理程序”。这是一个
StreamHandler
写入到sys.stderr
,级别为WARNING
,用于在没有任何日志配置的情况下处理日志记录事件。最终结果是只是将消息打印到sys.stderr
。这将替换先前的错误消息,说“没有处理程序可以找到记录器XYZ”。如果由于某种原因需要早期行为,可以将lastResort
设置为None
。版本3.2中的新功能。
16.6.12. Integration with the warnings module¶
captureWarnings()
函数用来将logging
与warnings
模块集成。
-
logging.
captureWarnings
(capture)¶ 该函数用来打开/关闭“日志捕获警告”。
如果capture为
True
,warnings
模块产生的警告会被重定向至日志系统。警告会被用warnings.formatwarning()
来格式化,结果字符串会被名字为'py.warnings'
的logger所记录,严重程度为WARNING
。如果捕获为
False
,则警告重定向到日志系统将停止,并且警告将重定向到其原始目的地。调用captureWarnings(True)
之前有效的那些。
参见
- 模块
logging.config
- 日志模块的配置API。
- 模块
logging.handlers
- 日志模块带的有用的handler。
- PEP 282 - 日志系统
- 包含于Python标准库描述该功能的提案。
- 原始的Python日志包
logging
包的原始源码。该站点此版本的包适用与Python 1.5.2, 2.1.x 和 2.2.x,在这些版本的Python标准库中并不保护logging
包。