Python的 logging 模块(一)

简介

该模块定义了为应用程序和库实现灵活的事件日志系统的函数和类。

使用标准库模块提供的日志API的主要好处是,所有Python模块都可以参与日志记录,因此您的应用程序日志可以包含与来自第三方模块的消息集成的消息。

该模块提供了很多功能和灵活性。如果您不熟悉日志记录,了解它的最佳方法是查看教程(参见下面的链接)。

重要:

此页面仅包含API参考信息。恶女多关于高级主题的教程信息和讨论,请参阅:

模块定义的类和函数如下所示:

  • Logger 暴露了应用程序代码直接使用的接口。
  • Handler 将由Logger创建的日志记录发送到合适的目标
  • Filter 提供了更精细的设施,用于确定要输出的日志记录
  • Formatter 指定最终输出的日志记录的格式

为了便于描述,下面的内容中,Logger 统称为 记录器,Handler 统称为 处理器,Filter 统称为 过滤器,Formatter 统称为 格式化器

类和方法详解

Logger 对象

记录器具有以下属性和方法。请注意,记录器从未直接实例化,而是始终通过模块级函数 log.getLogger(name) 实例化。对具有相同名称的 getLogger() 的多次调用总是返回对同一个 Logger 对象的引用。

name 可以是一个周期分隔的层次值(period-separated hierarchical value),如foo.bar.baz (例如,也可以是 foo)。在层次结构列表中较低位置的记录器是列表中较高位置的记录器的子记录器。例如,给定一个名为 foo 的记录器,则名为 foo.barfoo.bar.bazfoo.bam 的记录器都是 foo 的后代。记录器名称层次结构类似于Python包层次结构,如果使用推荐的方式 logging.getLogger(_name__) 在每个模块上组织记录器,则与之相同。这是因为在模块中,__name__ 是Python包命名空间中的模块名称。

class logging.Logger

  • propagate

    如果此属性的值为 True,则记录到此记录器的事件将被传递给更高级别(祖先)的记录器的处理器,以及附加到此记录器的任何处理器。消息直接传递给祖先记录器的处理器 —— 不考虑相关祖先记录器的级别或过滤器。

    如果为 False,则不会将日志消息传递给祖先记录器的处理器。

    构造函数将此属性设置为 True

    注意:

    如果将处理器附加到日志程序及其一个或多个祖先,它可能会多次发出相同的记录。一般来说,应该不需要将一个处理器附加到多个记录器 —— 如果你只是把处理器附加到位于记录器的层次结构中位置最高的记录器上,那么处理器将会看到由这个记录器的所有后代记录的所有事件,前提是这些后代的传播设置均设置为 True。一种常见的场景是只将处理器附加到根记录器,并让传播处理剩下的工作。

  • setLevel(level)

    设置此记录器的阈值为 level。严重程度低于 level 的日志记录消息将被忽略;严重级别等于或大于 level 的日志记录消息将由任何处理程序或为该记录器提供服务的处理器发出,除非将处理程序的级别设置为比 level 更高的严重级别。

    创建记录器时,将级别设置为 NOTSET (当记录器是根记录器时,将处理所有消息,当记录器是非根记录器时,将委托给父进程)。注意,根记录器是用级别 warning 创建的。

    术语 委托给父记录器 意味着,如果一个记录器具有 NOTSET 级别,那么它的祖先记录器链将被遍历,直到找到具有 NOTSET 以外级别的祖先,或者到达根。

    如果发现祖先的级别不是 NOTSET,则将该祖先的级别视为祖先搜索开始的记录器的有效级别,并用于确定如何处理日志事件。

    如果到达根节点,并且根节点的级别为 NOTSET,那么将处理所有消息。否则,根级别将用作有效级别。

  • isEnabledFor(lvl)

    指示此记录器是否将处理严重级别为 lvl 的消息。该方法首先检查 logger .disable(lvl) 设置的模块级别的级别,然后检查 getEffectiveLevel() 确定的记录器的有效级别。

  • getEffectiveLevel()

    指示此记录器的有效级别。如果使用 setLevel() 设置了 NOTSET 以外的值,则返回该值。否则,层次结构将遍历到根,直到找到 NOTSET 之外的值并返回该值。返回的值是一个整数,通常是 logging.DEBUGlogging.INFO 等表示的整数。

  • getChild(suffix)

    返回一个由 suffix 确定的当前记录器的后代记录器。因此 logging.getLogger('abc').getChild('def.ghi') 将会返回与 logging.getLogger('abc.def.ghi') 返回的相同记录器相同的记录器。这是一个方便的方法,在父记录器的名字由 __name__ 而不是字符串字面量命名时是很有用的。

  • debug(msg, *args, **kwargs)

    在此记录器上记录带有级别 DEBUG 的消息。msg 是消息格式字符串,args 是使用字符串格式操作符合并到 msg 中的参数。(注意,这意味着您可以在格式字符串中使用关键字,以及单个字典参数。)

    kwargs 中有三个关键字参数需要检查:exc_infostack_infoextra

    如果 exc_info 不是 False,则会导致异常信息被添加到日志消息中。如果提供了异常元组(形如 sys.exc_info() 函数的返回值)或异常实例,则使用异常元组;否则,将调用 sys.exc_info() 来获取异常信息。

    第二个可选关键字参数是 stack_info,默认为 False。如果为 True,则将堆栈信息添加到日志消息中,包括实际的日志调用。注意,这是与通过指定 exc_info 显示的不相同的堆栈信息:前者是堆栈底部到当前线程中的日志调用的堆栈帧,而后者是关于已经被解除的后面跟着一个搜索异常处理程序的异常的堆栈帧的信息。

    您可以独立于 exc_info 指定 stack_info,例如,即使当没有引发异常时,也可以仅显示如何到达代码中的某个点。堆栈帧按标题行打印,该标题行表示:

    Stack (most recent call last):
    

    这类似于用于显示异常帧的 Traceback (most recent call last)

    第三个关键字参数是 extra,它可以用来传递一个字典,这个字典用来用用户定义的属性填充为日志事件创建的日志记录的 __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 对象) 文档。)

    如果您选择在已记录的消息中使用这些属性,则需要多加注意。例如,在上面的示例中,格式化器已经用一个格式字符串设置好了,该格式字符串期望在LogRecord 的属性字典中包含 clientipuser。如果缺少这些,则不会记录消息,因为将发生字符串格式化异常。在这种情况下,你总是需要用这些键传递 extra 字典。

    虽然这可能是很恼人的,这个功能是用于专门的情况下,例如,在许多上下文中执行相同代码的多线程服务器,以及由此产生的有趣条件都依赖于此上下文(例如,在上面的示例中,远程客户机IP地址和经过身份验证的用户名)。。在这种情况下,可能会将专用格式化器与特定的处理器一起使用。

  • info(msg, *args, **kwargs)

    在这个记录器上记录级别为 INFO 的消息。参数的解释与 debug() 相同。

  • warning(msg, *args, **kwargs)

    在这个记录器上记录级别为 RARNING 的消息。参数的解释与 debug() 相同。

    注意:

    有一个与 warning 方法功能相同的废弃的方法 warnwarn 方法已经弃用,请使用 warning 方法代替。

  • error(msg, *args, **kwargs)

    在这个记录器上记录级别为 ERROR 的消息。参数的解释与 debug() 相同。

  • critical(msg, *args, **kwargs)

    在这个记录器上记录级别为 CRITICAL 的消息。参数的解释与 debug() 相同。

  • log(lvl, msg, *args, **kwargs)

    在这个记录器上记录一条使用使用整数 lvl 表示严重级别的消息。参数的解释与 debug() 相同。

  • exception(msg, *args, **kwargs)

    在记录器上记录一条级别为 ERROR 的消息。参数的解释与 debug() 相同。异常信息会添加到日志消息中。这个方法只应该在异常处理器中进行调用。

  • addFilter(filter)

    将制定的过滤器 filter 添加到记录器中。

  • removeFilter(filter)

    从记录器中移除制定的过滤器 filter

  • filter(record)

    将此日志记录器的过滤器应用于记录,如果要处理记录,则返回一个真值。依次查询过滤器,直到其中一个返回一个假值。如果它们都没有返回一个假值,那么记录将被处理(传递给处理器)。如果返回一个假值,则不会对记录进行进一步处理。

  • addHandler(hdlr)

    将指定的处理器 hdlr 添加到记录器。

  • removeHandler(hdlr)

    将指定的记录器 hdlr 从记录器中移除。

  • findCaller(stack_info=False)

    查找调用者的源文件名和行号。将文件名,行号,方法名和堆栈信息做为一个四元组返回。除非 stack_infoTrue,否则堆栈信息将作为 None 返回。

  • handle(record)

    通过将记录传递给与此记录器及其祖先关联的所有处理器来处理记录(直到找到一个为 Falsepropagate 值)。此方法用于从套接字接收的未pickle记录,以及本地创建的记录。使用 filter() 应用记录器级级的过滤。

  • makeReord(name, lvl, fn, lno, msg, args, exc_info, func=None, extra=None, sinfo=None)

    这个工厂方法可以被子类重写,以创建专门的 LogRecord 实例。

  • hasHandlers()

    检查此记录器是否配置了任何处理器。这是通过在这个记录器中查找处理器以及在记录器层次结构中查找它的父类来实现的。如果找到处理器,则返回 *True,否则返回 False。当发现一个将 propagate 属性设置为 False 的记录器时,该方法将停止在层次结构中进行搜 索——这将是检查处理器是否存在的最后一个记录器。

日志级别

日志级别的数值在下表中给出。如果你想要定义自己的级别,并且需要它们具有相对于预定义级别的特定值,那么这些内容可能是你感兴趣的。如果你定义具有相同数值的级别,它将覆盖预定义的值,并且预定义的名称将会丢失。

LevelNumeric value
CRITICAL50
ERROR40
WARNING30
INFO20
DEBUG10
NOTSET0

Handler 对象

Handler 对象包含下面的属性和方法。注意,Handler 从未直接实例化。这个作为更有用的子类的基类。在子类的 __init__() 方法中需要调用 Handler.__init__()

class logging.Handler

  • __init__(level=NOTSET)

    通过设置处理器实例的级别、将过滤器列表设置为空列表并创建一个锁(使用creatock())来序列化对I/O机制的访问,从而初始化该处理器实例。

  • createLock()

    初始化一个线程锁,该线程锁可用于序列化对底层I/O功能的访问,而底层I/O功能可能不是线程安全的。

  • acquire()

    获取使用 createLock() 创建的线程锁。

  • release()

    释放使用 acquire() 获取的线程锁。

  • setLevel(level)

    将此处理器的阈值设置为 level。级别小于 level 的消息将会被忽略。创建处理器时,将级别设置为 NOTSET (这会导致处理所有消息)。

    有关级别列表,请参见 日志级别

  • setFormatter(fmt)

    将这个处理器的格式化器设置为 fmt

  • addFilter(filter)

    将指定的过滤器 filter 添加到这个处理器。

  • removeFilter(filter)

    从这个处理器中将指定的过滤器 filter 移除。

  • filter(record)

    将此处理器的过滤器应用于记录,如果要处理记录,则返回一个真值。依次查询过滤器,直到其中一个返回一个假值。如果它们都没有返回假值,则将发出该记录。如果返回一个假值,处理器将不会发出该记录。

  • flush()

    确保所有日志输出都已被刷新。这个版本什么也不做,打算由子类实现。

  • close()

    整理处理器使用的所有资源。这个版本没有输出,但是从调用 shutdown() 时关闭的内部处理器列表中删除处理器。子类应该确保从覆盖的 close() 方法调用这个函数。

  • handle()

    根据可能添加到处理器的过滤器,有条件地发出指定的日志记录。用获取/释放I/O线程锁来封装记录的实际释放。

  • handleError(record)

    当在 emit() 调用期间遇到异常时,应该从处理器调用此方法。如果模块级属性 raiseexceptionFalse,异常将被悄然忽略。这是日志系统最需要的 ——大多数用户不关心日志系统本身的错误,他们对应用程序错误更感兴趣。但是,如果您愿意,您可以用自定义处理器替换它。指定的记录是发生异常时正在处理的记录。(raiseexception 的默认值为 True,因为它在开发期间更有用)。

  • format(record)

    如果已经设置了一个格式化器,则使用它对一条记录执行格式化。否则,使用模块默认的格式化器。

  • emit(record)

    尽一切可能记录指定的日志记录。这个版本打算由子类实现,因此会引发一个NotImplementedError

有关作为标准包含的处理程序列表,请参见 logging .handlers

Formatter 对象

Formatter 对象有如下的属性和方法。它们负责将一个 LogRecord 转换成可以被人类或者外部系统解释的字符串。基础的格式化器允许指定一个格式化字符串。如果未提供,则使用只在日志记录调用中包含消息的默认值 %(message)s。要在格式化输出中包含额外的信息项(例如时间戳),请继续阅读。

格式化器可以使用一个格式字符串初始化,该字符串利用了 LogRecord 属性的知识——例如上面提到的默认值,利用了这样一个事实,即用户的消息和参数被预先格式化为 LogRecordmessage 属性。此格式字符串包含标准Python 百分号(%)样式的映射键。

在 [LogRecord 属性](# LogRecord 属性) 一节中给出了LogRecord中有用的映射键。

class logging.Formatter(fmt=None, datefmt=None, style=‘%’)

返回 Formatter 类的一个新实例。实例初始化时使用整个消息的格式字符串,以及消息的日期/时间部分的格式字符串。如果没有指定 fmt,则使用 %(message)s。如果没有指定 datefmt,则使用 formatTime() 文档中描述的格式。

style 参数可以是 %{$ 中的一个,并确定格式字符串将如何与其数据合并:使用 %-formattingstr.format()string. template 中的一个。有关使用 {-$- 格式化日志消息的更多信息,请参阅 在整个应用程序中使用特定的格式化样式

  • format(record)

    记录的属性字典用作字符串格式化操作的操作数。返回结果字符串。在格式化字典之前,要执行几个准备步骤。记录的 message 属性使用 msg % args 计算。如果格式化字符串包含 '(asctime)’,则调用 formatTime() 格式化事件时间。如果有异常信息,则使用 formatException() 对其进行格式化,并将其附加到消息中。注意,格式化的异常信息缓存在属性 exc_text 中。这很有用,因为异常信息可以通过网络进行pickle和发送,但是如果您有多个 Formatter 子类,用于定制异常信息的格式化,那么您应该小心。在这种情况下,您必须在格式化器完成格式化后清除缓存的值,以便下一个处理事件的格式化器不会使用缓存的值,而是重新计算它。

    如果堆栈信息可用,它将附加在异常信息之后,在必要时使用 formatStack() 对其进行转换。

  • formatTime(record, datefmt=None)

    希望使用格式化时间的格式化器应该从 format() 调用此方法。在格式化起中可以重写此方法以满足任何特定的需求,但基本行为如下:如果指定了 datefmt (字符串),则将它与 time.strftime() 一起使用,以格式化记录的创建时间。否则,将使用格式 ' %Y-%m-%d %H:% m:%S,uuu ‘,其中 uuu 部分是一个毫秒值,其他字母按照 time.strftime() 文档。这种格式的示例时间是 2003-01-23 00:29:29 50,411。返回结果字符串。

    此方法使用用户可配置的函数将创建时间转换为元组。默认情况下使用time.localtime();要为特定格式化器实例更改此属性,请将 converter 属性设置为与 time.localtime()time.gmtime() 具有相同签名的函数。要为所有格式化器更改它,例如,如果希望所有日志记录时间都以GMT显示,请在 Formatter 类中设置 converter 属性。

  • formatException(exc_info)

    将指定的异常信息(由 sys.exc_info() 返回的标准异常元组)格式化为字符串。这个默认实现只使用 traceback.print_exception()。返回结果字符串。

  • formatStack(stack_info)

    将指定的堆栈信息(traceback.print_stack() 返回的字符串,但删除了最后一行)格式化为字符串。这个默认实现只返回输入值。

Filter 对象

处理程序和日志记录器可以使用过滤器进行比级别提供的过滤更复杂的过滤。基本过滤器类只允许记录器层次结构中某一点以下的事件。例如,一个使用 A.B 初始化的过滤器。将会允许记录器 A.BA.B.CA.B.C.DA.B.D 等记录事件,但是不允许 A.BBB.A.B 等记录事件。如果使用空字符串初始化,则所有事件都可以通过。

class logging.Filter(name=’’)

返回一个 Filter 类的新实例。如果指定了 name 参数,它将命名一个记录器,该记录器及其子记录器将允许其事件通过过滤器。如果 name 参数是空字符串,则允许所有事件。

  • filter(record)

    是否要记录指定的记录?返回0表示不,非0表示是。如果认为合适,可以用这种方法就地修改记录。

注意,附加到处理器的过滤器是在处理器发出事件之前被查询的,而附加到记录器的过滤器是在记录事件(使用 debug()info()等)、发送事件到处理器之前被查询的。这意味着由后代记录器生成的事件不会被记录器的过滤器设置过滤,除非过滤器也应用于这些后代记录器。

您实际上不需要子类化 Filter:您可以传递具有相同语义的 filter 方法的任何实例。

您不需要创建专门的过滤器类,也不需要使用带有过滤器方法的其他类:您可以使用函数(或其他可调用对象)作为过滤器。筛选逻辑将检查筛选器对象是否具有筛选器属性:如果有,则假定它是筛选器,并调用它的 filter() 方法。否则,假定它是一个可调用对象,并将记录作为单个参数调用。返回的值应该与 filter() 返回的值一致。

尽管过滤器主要基于比级别更复杂的标准进行过滤,他们可以看到被他们要连接到的处理器或过滤器所处理的每一个记录:如果您想计算某个特定的日志记录器或处理程序处理了多少条记录,或者在正在处理的日志记录中添加、更改或删除属性,这将非常有用。显然,修改 LogRecord 需要谨慎一些,但是它允许将上下文信息注入日志(请参阅 使用过滤器传递上下文信息)。

LogRecord 对象

LogRecord 实例是由记录器在每次记录某些内容时自动创建的,并且可以通过makeLogRecord() 手动创建(例如,从通过网络接收的pickle事件中创建)。

class logging.LogRecord(name, level, pathname, lineno, msg, args, exc_info, func=None, sinfo=None)

包含与正在记录的事件相关的所有信息。

参数解释:

主要信息以 msgargs 的形式传递,它们使用 msg % args 组合在一起来创建记录的消息字段。

  • name:用于记录由该LogRecord表示的事件的记录器的名称。注意,这个名称将始终具有这个值,即使它可能由附加到不同(祖先)记录器的处理程序发出。
  • level:日志事件的数值级别(DEBUGINFO 等之一)注意,这被转换为LogRecord的两个属性:表示数值值的 levelno 和对应的级别名称 levelname
  • pathname:发出日志记录调用的源文件的完整路径名。
  • lineno:发出日志记录调用的源文件中的行号。
  • msg:事件描述消息,可能是带有变量数据的占位符的格式字符串。
  • args:要合并到 msg 参数中的变量数据,以获得事件描述。
  • exc_info:包含当前异常信息的异常元组,如果没有可用的异常信息,则为 None
  • func:调用日志记录调用的函数或方法的名称。
  • sinfo:一个文本字符串,表示从当前线程的堆栈基到日志调用的堆栈信息。

LogRecord实例对象有一个公开的方法;

  • getMessage()

    将用户提供的参数与该消息合并后,返回此LogRecord实例的消息。如果日志记录调用的用户提供的消息参数不是字符串,则对其调用 str() 将其转换为字符串。这允许使用用户定义的类作为消息,它的 __str__ 方法可以返回要使用的实际格式字符串。

此功能可用于在创建时将您自己的值注入到日志记录中。您可以使用以下模式:

old_factory = logging.getLogRecordFactory()

def record_factory(*args, **kwargs):
    record = old_factory(*args, **kwargs)
    record.custom_attribute = 0xdecafbad
    return record

logging.setLogRecordFactory(record_factory)

使用这种模式,可以链接多个工厂,只要它们不覆盖彼此的属性或无意中覆盖上面列出的标准属性,就不会出现意外。

LogRecord 属性

LogRecord有许多属性,其中大部分是从构造函数的参数派生出来的。(注意,名称并不总是与LogRecord构造函数参数和LogRecord属性完全对应。)这些属性可用于将记录中的数据合并到格式字符串中。下表以%样式的格式字符串列出(按字母顺序)属性名、它们的含义和对应的占位符。

如果使用 {}-formattingstring. format()),可以使用 {attrname} 作为格式字符串中的占位符。如果您正在使用 $-formattingstring.Template),请使用 ${attrname} 这种形式。当然,在这两种情况下,都要用想要使用的实际属性名替换 attrname

在使用 {}-formatting 的情况下,您可以通过将它们放在属性名后面来指定格式化标志,并使用冒号将它们与属性名分隔开。例如 :{msecs:03d} 的占位符将把毫秒值 4 格式化为 004

属性名FormatDescription
argsYou shouldn’t need to format this yourself.The tuple of arguments merged into msg to produce message, or a dict whose values are used for the merge (when there is only one argument, and it is a dictionary).
asctime%(asctime)sHuman-readable time when the LogRecord was created. By default this is of the form ‘2003-07-08 16:49:45,896’ (the numbers after the comma are millisecond portion of the time).
created%(created)fTime when the LogRecord was created (as returned by time.time()).
exc_infoYou shouldn’t need to format this yourself.Exception tuple (à la sys.exc_info) or, if no exception has occurred, None.
filename%(filename)sFilename portion of pathname.
funcName%(funcName)sName of function containing the logging call.
levelname%(levelname)sText logging level for the message ('DEBUG', 'INFO', 'WARNING','ERROR', 'CRITICAL').
levelno%(levelno)sNumeric logging level for the message (DEBUG, INFO, WARNING, ERROR,CRITICAL).
lineno%(lineno)dSource line number where the logging call was issued (if available).
message%(message)sThe logged message, computed as msg %args. This is set whenFormatter.format() is invoked.
module%(module)sModule (name portion of filename).
msecs%(msecs)dMillisecond portion of the time when theLogRecord was created.
msgYou shouldn’t need to format this yourself.The format string passed in the original logging call. Merged with args to produce message, or an arbitrary object (see Using arbitrary objects as messages).
name%(name)sName of the logger used to log the call.
pathname%(pathname)sFull pathname of the source file where the logging call was issued (if available).
process%(process)dProcess ID (if available).
processName%(processName)sProcess name (if available).
relativeCreated%(relativeCreated)dTime in milliseconds when the LogRecord was created, relative to the time the logging module was loaded.
stack_infoYou shouldn’t need to format this yourself.Stack frame information (where available) from the bottom of the stack in the current thread, up to and including the stack frame of the logging call which resulted in the creation of this record.
thread%(thread)dThread ID (if available).
threadName%(threadName)sThread name (if available).

LoggerAdapter 对象

LoggerAdapter 实例用于方便地将上下文信息传递到日志记录调用中。有关使用示例,请参阅 向日志输出添加上下文信息

class logging.LoggerAdapter(logger, extra)

返回一个使用底层 Logger 实例和一个类字典对象实例化的 LoggerAdapter 实例。

  • process(msg, kwargs)

    修改传递给日志记录调用的消息和/或关键字参数,以便插入上下文信息。这个实现接受作为构造函数的 extra 参数进行传递的对象,并使用键 'extra' 将其添加到 kwargs中。返回值是一个 (msg, kwargs) 元组,它具有传入参数的 (可能修改过的)版本。

除了上述方法之外,LoggerAdapter 还支持 Logger 的以下方法:

  • debug()
  • info()
  • warning()
  • error()
  • exception()
  • critical()
  • log()
  • isEnabledFor()
  • getEffectiveLevel()
  • setLevel()
  • hasHandlers()

这些方法与 Logger 中的对应方法具有相同的签名,因此可以互换使用这两种类型的实例。

线程安全

日志模块是线程安全的,不需要客户机执行任何特殊的工作。它通过使用线程锁来实现这一点;有一个锁来序列化对模块共享数据的访问,每个处理器还创建一个锁来序列化对其底层I/O的访问。

如果使用信号模块实现异步信号处理器,则可能无法在此类处理器中使用日志记录。这是因为线程模块中的锁实现并不总是可重入的,因此不能从此类信号处理程序器。

模块级别函数

除了上面描述的类之外,还有一些模块级函数。

  • logging.getLogger(name=None)

    返回具有指定名称的日志程序,或者,如果 nameNone,则返回层次结构的根记录器。如果指定 name,则通常是一个使用点号分隔的层次结构名称,如 ’a’’a.b’’a.b.c.d’。这些名称的选择完全取决于使用日志的开发人员。

    使用给定名称调用此函数的所有调用都返回相同的记录器实例。这意味着从来不需要在应用程序的不同部分之间传递记录器实例。

  • logging.getLoggerClass()

    返回标准 Logger 类,或者传递给 setLoggerClass() 的最后一个类。可以在新的类定义中调用此函数,以确保安装自定义记录器类不会撤消其他代码已经应用的自定义记录器类。例如:

    class MyLogger(logging.getLoggerClass()):
        # ... override behaviour here
    
  • logging.getLogRecordFactory()

    返回用于创建 LogRecord 的可调用对象。

  • logging.debug(msg, *args, **kwargs)

    在根记录器上记录带有级别 DEBUG 的消息。msg 是消息格式字符串,args 是使用字符串格式操作符合并到 msg 中的参数。(注意,这意味着您可以在格式字符串中使用关键字,以及单个字典参数。)

    kwargs 中有三个关键字参数需要检查:exc_infostack_infoextra

    如果 exc_info 不是 False,则会导致异常信息被添加到日志消息中。如果提供了异常元组(形如 sys.exc_info() 函数的返回值)或异常实例,则使用异常元组;否则,将调用 sys.exc_info() 来获取异常信息。

    第二个可选关键字参数是 stack_info,默认为 False。如果为 True,则将堆栈信息添加到日志消息中,包括实际的日志调用。注意,这是与通过指定 exc_info 显示的不相同的堆栈信息:前者是堆栈底部到当前线程中的日志调用的堆栈帧,而后者是关于已经被解除的后面跟着一个搜索异常处理程序的异常的堆栈帧的信息。

    您可以独立于 exc_info 指定 stack_info,例如,即使当没有引发异常时,也可以仅显示如何到达代码中的某个点。堆栈帧按标题行打印,该标题行表示:

    Stack (most recent call last):
    

    这类似于用于显示异常帧的 Traceback (most recent call last)

    第三个关键字参数是 extra,它可以用来传递一个字典,这个字典用来用用户定义的属性填充为日志事件创建的日志记录的 __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 对象) 文档。)

    如果您选择在已记录的消息中使用这些属性,则需要多加注意。例如,在上面的示例中,格式化器已经用一个格式字符串设置好了,该格式字符串期望在LogRecord 的属性字典中包含 clientipuser。如果缺少这些,则不会记录消息,因为将发生字符串格式化异常。在这种情况下,你总是需要用这些键传递 extra 字典。

    虽然这可能是很恼人的,这个功能是用于专门的情况下,例如,在许多上下文中执行相同代码的多线程服务器,以及由此产生的有趣条件都依赖于此上下文(例如,在上面的示例中,远程客户机IP地址和经过身份验证的用户名)。。在这种情况下,可能会将专用格式化器与特定的处理器一起使用。

  • logging.info(msg, *args, **kwargs)

    在根记录器上记录级别为 INFO 的消息。参数的解释与 debug() 相同。

  • logging.warning(msg, *args, **kwargs)

    在根记录器上记录级别为 WARNING 的消息。参数的解释与 debug() 相同。

    注意:

    有一个与 warning 方法功能相同的废弃的方法 warnwarn 方法已经弃用,请使用 warning 方法代替。

  • logging.error(msg, *args, **kwargs)

    在根记录器上记录级别为 ERROR 的消息。参数的解释与 debug() 相同。

  • logging.critical(msg, *args, **kwargs)

    在根记录器上记录级别为 CRITICAL 的消息。参数的解释与 debug() 相同。

  • logging.exception(msg, *args, **kwargs)

    在根记录器上记录级别为 ERROR 的消息。参数的解释与 debug() 相同。

    异常信息会添加到日志消息中。这个方法只应该在异常处理器中进行调用。

  • logging.log(level, msg, *args, **kwargs)

    在根记录器上记录级别为 level 的消息。参数的解释与 debug() 相同。

    注意:

    上面的模块级便利函数委托给根日志记录器,调用 basicConfig() 以确保至少有一个处理器可用。因此,它们不应该在线程中使用,在比2.7.1和3.2更早的Python版本中,除非在线程启动之前至少向根记录器添加了一个处理器。在Python的早期版本中,由于 basicConfig() 中的线程安全缺陷,这可能(在很少的情况下)导致处理器被多次添加到记录器中,而根记录器又可能导致同一事件的多条消息。

  • logging.disable(lvl=CRITICAL)

    为所有记录器提供覆盖级别 lvl,它优先于记录器自己的级别。当需要在整个应用程序中临时限制日志输出时,这个函数可能很有用。它的作用是禁用严重性 lvl 及以下的所有日志调用,这样,如果您使用 INFO 值调用它,那么所有 INFODEBUG 事件都将被丢弃,而 WARNING 及以上的事件将根据日志程序的有效级别进行处理。如果调用 log.disable(log.NOTSET),它将有效地删除这个覆盖级别,这样日志输出将再次依赖于各个记录器的有效级别。

    注意,如果您定义了任何高于临界值的自定义日志记录级别(不建议这样做),那么您将不能依赖 lvl 参数的默认值,但是必须显式地提供一个合适的值。

  • logging.addLevelName(lvl, levelName)

    将级别 lvl 与内部字典中的文本 levelName 关联起来,后者用于将数值级别映射到文本表示形式,例如格式化器格式化消息时。这个函数也可以用来定义您自己的级别。唯一的限制是所有使用的级别必须使用这个函数注册,级别应该是正整数,并且它们应该按照严重程度递增的顺序递增。

    注意:如果想要自定义你自己的级别,请查看 自定义级别

  • logging.getLevelName(lvl)

    返回日志级别 lvl 的文本表示形式。如果该级别是预定义的关键级别 CRITICALERRORWARNINGINFODEBUG 之一,那么您将得到相应的字符串。如果使用 addLevelName() 将级别与名称关联,则返回与 lvl 关联的名称。如果传入与定义的级别之一对应的数值,则返回相应的字符串表示形式。否则,将返回字符串 "Level %s” % lvl

    注意:

    级别是内部整数(因为它们需要在日志逻辑中进行比较)。此函数用于通过 %(levelname) 格式说明符在整数级别和格式化日志输出中显示的级别名称之间进行转换(参见 [LogRecord属性](#LogRecord 属性))。

  • logging.makeLogRecord(attrdict)

    创建并返回一个新的 LogRecord 实例,该实例的属性由 attrdict 定义。该函数用于获取经过pickle的 LogRecord 属性字典(通过套接字发送),并在接收端将其重新构造为 LogRecord 实例。

  • logging.basicConfig(**kwargs)

    使用默认格式化器创建 StreamHandler 并将其添加到根记录器中,从而完成日志系统的基本配置。如果没有为根记录器定义处理器,debug()info()warning()error()critical() 函数将自动调用basicConfig()

    如果根记录器已经配置了处理器,则此函数不执行任何操作。

    注意:这个函数应该在其他线程启动之前从主线程调用。在2.7.1和3.2之前的Python版本中,如果从多个线程调用此函数,则可能(在很少的情况下)不止一次地将处理器添加到根记录器中,从而导致意想不到的结果,比如在日志中复制消息。

    该方法支持下面的关键字参数:

    FormatDescription
    filename使用指定的文件名而不是StreamHandler创建FileHandler。
    filemode如果指定了 filename,则使用该参数的指定的模式打开文件。默认值是 'a'
    format为处理器使用指定的格式字符串。
    datefmt使用指定的日期/时间格式,就像 time.strftime() 接受的格式一样。
    style如果指定了 format ,则为格式字符串使用这个样式。 可以是 '%''{''$' 之一 。 默认值是 '%'.
    level将跟记录器的级别设置为 level
    stream使用指定的流初始化 StreamHandler。注意,这个参数与filename不兼容 —— 如果两者都存在,就会引发一个 ValueError 异常。
    handlers如果指定,这应该是已经创建的处理器的可迭代对象,以便添加到根记录器中。任何没有格式化器集合的处理器都将被分配给在此函数中创建的默认格式化器。注意,此参数与 filenamestream 不兼容——如果两者都存在,则会引发 ValueError 异常。
  • logging.shutdown()

    通知日志系统通过刷新和关闭所有处理器来执行有序关闭。这应该在应用程序退出时调用,并且在调用之后不应该进一步使用日志系统。

  • logging.setLoggerClass(klass)

    告诉日志系统在实例化记录器时使用类 klass。类应该定义 __init__(),这样只需要一个名称参数,并且 __init__() 应该调用 Logger.__ init__() 方法。此函数通常在需要使用自定义记录器行为的应用程序实例化任何记录器之前调用。

  • logging.setLogRecordFactory(factory)

    设置用于创建 LogRecord 的可调用对象。

    factory 参数应该是一个可调用对象,用于实例化一个日志记录。

    factory 的签名如下:

    factory(name, level, fn, lno, msg, args, exc_info, func=None, sinfo=None, **kwargs)

    • name:记录器的名称。
    • level:日志记录的级别(数值)。
    • fn:发出日志记录调用的文件的完整路径名。
    • lno:发出日志记录调用的文件中的行号。
    • msg:日志记录消息。
    • args:日志记录消息的参数。
    • exc_info:一个异常元组或者 None
    • func:调用日志记录调用的函数或方法的名称。
    • sinfo:堆栈回溯,如 traceback.print_stack() 提供的,显示调用层次结构。
    • kwargs:额外的关键字参数。

模块级别属性

  • logging.lastResort

    handler of last resort 可通过此属性获得。这是向 sys.stderr 写入的 StreamHandler,具有级别 WARNING,并用于在没有任何日志配置的情况下处理日志事件。最终的结果是将消息打印到 sys.stderr。这将替换前面的错误消息,即 无法为记录器XYZ找到处理程序。如果出于某种原因需要早期行为,可以将lastResort 设置为 None

与warning模块集成

captureWarnings 函数可用于将 logging 模块与 warning 模块集成在一起。

  • logging.captureWarnings(capture)

    此函数用于通过开启和关闭来关闭警告的捕获。

    如果 captureTrue,警告模块发出的警告将被重定向到日志系统。具体来说,警告将使用 warning .formatwarning() 进行格式化和记录到名为 py.warnings 的记录器,级别为 WARNING

    如果 captureFalse,则警告将停止重定向到日志系统,警告将重定向到原始目的地(即在调用 captureWarnings(True) 之前有效的目的地)。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值