在代码中实现可选的记录器

时间:2012-11-23 01:05:04

标签: python logging

我想在函数中实现可选的记录器。类似的东西:

def foo(arg1, arg2, arg3, logger=None):
    logger = logger or (lambda *x: None)

    ...
    self.logger.debug("The connection is lost.")

我希望在记录器存在的情况下进行日志记录。否则,记录器的调试将不起作用。

基本上,实现它的简单方法是将每个调试语句嵌套在if logger块中,但是当有许多调试语句时它似乎很乱。

6 个答案:

答案 0 :(得分:7)

几个选项:

创建一个虚拟记录器(我最喜欢的):

logger = logger or logging.getLogger('dummy') #  without configuring dummy before.

创建一个具有一级null效果的虚拟对象

class DummyObject(object):
    def __getattr__(self, name):
        return lambda *x: None

logger = logger or DummyObject()

将每个调试语句嵌套在一个块中:

if logger:
    logger.debug("abc")

答案 1 :(得分:6)

自Python 2.7以来,logging模块中包含无操作NullHandler

import logging      
logging.getLogger('foo').addHandler(logging.NullHandler())

请参阅configuring logging for a library的文档。

答案 2 :(得分:2)

那就是logging模块的用途。 How to useCookbook

如果你真的想自己动手,我会看到一些选择:

  • self.logger属性。在构造对象时设置或从基类继承。每个对象都有自己的记录器,因此您可以对每个实例进行选择性记录。

  • 使用静态方法或独立模块的记录器类。可能有默认方法什么都不做,但用户可以随时用真正的处理程序替换它们。所有类都访问相同的对象或模块。丢失粒度,但设置工作较少。

  • <强> Decorators 即可。在要记录的每个方法上方放置@log('message', LEVEL),这将在调用方法时自动调用日志。相当清洁,灵活性较差。

答案 3 :(得分:1)

我认为你想要的是日志过滤, 所以我的答案是关于如何简单地实现日志过滤。

Python的日志包已经完成了这项工作,您可以通过多种方式进行日志记录过滤。

两种基本方式是:

  • 日志级别过滤
  • 记录器名称过滤

它们都使用日志记录的配置,因此可以轻松配置。

例如:

import logging

logging.basicConfig()  # easily setup a StreamHandler output

logging.getLogger("realm1").setLevel(logging.WARNING)
logging.getLogger("realm2").setLevel(logging.INFO)

def test():
    r1logger = logging.getLogger("realm1")
    r2logger = logging.getLogger("realm2")
    r1logger.info('r1 info')  # won't print
    r2logger.info('r2 info')  # will print

if __name__ == '__main__':
    test()

因此,除非您需要运行时动态本地更改日志记录策略, 使用默认记录器并仔细记录配置就足够了。

答案 4 :(得分:1)

默认情况下,调用 logging.getLogger 时用于构造新记录器的类是 logging.Logger,默认情况下会将 propagate 属性设置为 True({{3 }})。根据文档,

<块引用>

如果此属性 [propagate] 的计算结果为 true,则除了附加到此记录器的任何处理程序之外,记录到此记录器的事件还将传递给更高级别(祖先)记录器的处理程序。

因此,只要记录器的父级之一具有一些重要的处理程序,@fcs 的答案就不会起作用,这很可能是这种情况,因为根记录器都是记录器的父级,并且它几乎总是具有 StreamHandler使用 stderr 流。

以下简单修复将起作用:

import logging
null_logger = logging.getLogger('foo')
null_logger.addHandler(logging.NullHandler())  # read below for reason
null_logger.propagate = False
null_logger.error("error")  # This message will still go nowhere

请注意,添加 logging.NullHandler 是必要的,因为如果日志记录未被任何处理程序处理,它将由 logging.lastResort 处理,它仍然会将此消息发送到 stderr(行为从 Python 3.2 开始)。

答案 5 :(得分:0)

您还可以做些什么,它要短一些,然后使用NullHander设置一个真正的记录器:

logger = Mock()