问题 在包模块中设置日志记录的有效方法


我有一个包含多个组件的包,这些组件将从使用日志记录和输出有用信息中受益匪浅。

我不想做的是为这些行中的某个地方的每个文件“设置”正确的日志记录:

import logging
logging.basicConfig(level=DEBUG)
my_function = logging.getLogger("my_function")
my_class = logging.getLogger("my_class")

我尝试了几种方法,其中一种方法是将样板代码添加到实用程序模块中的类中,并尝试执行以下操作:

from util import setlogging
set_logging()

但即使上面的解决方案看起来并不干净,也会导致问题,因为setLogger没有 __call__ 方法。我所喜欢的是我的“set_logging”类将从一个配置文件中读取并具有一些默认值,因此无论我想要什么级别或哪种类型的日志记录格式都可以正确设置它。

有没有办法在我的包中初始化正确的日志记录?也许在 __init__.py 文件?

只是为了尽可能冗长,这就是setlogging(现在是一个函数,而不是一个类)的样子:

def setlogging(config=None):
    if config == None:
        config = config_options() # sets default values
    levels = {
        'debug': DEBUG,
       'info': INFO
        }

    level = levels.get(config['log_level'])
    log_format = config['log_format']
    datefmt = config['log_datefmt']

    basicConfig(
        level   = level,
        format  = log_format,
        datefmt = datefmt)

8496
2017-07-28 00:08


起源



答案:


如果您希望程序包的各个模块中的所有代码都使用相同的记录器对象,您只需要(使该记录器可用 - 请参阅稍后 - 和)调用

mylogger.warning("Attenzione!")

等等,而不是 logging.warning &C。因此,问题减少到制作一个 mylogger 整个包的对象,并使其在包中的整个模块中可用。 (或者,您可以使用名称记录器,其名称以包名称开头,后跟一个点,但是这只是一个部分。 logging 包装功能,我个人从未发现它是一种自然的操作方式)。

所以,你的 util.setlogging 功能可以简单地跟随,比方说,

mylogger = logging.getLogger(package_name)

以及每个进口的模块 util 可以简单地使用

util.mylogger.warning('Watch out!')

等等。在我看来,这似乎是最简单的方法,只要包中的所有代码都应以相同方式登录的概念适用。


11
2017-07-28 00:27



难道我还不需要调用setlogging()来访问'mylogger'吗?即使我尝试了,我仍然得到一个预期的AttributeError,因为'function'对象没有属性'mylogger'。也许我没有完全了解情况...... - alfredodeza
@alfredo,它只需要被调用一次(来自包的 __init__.py 将是最简单的用于此目的的地方,因为你知道它总是在包中的任何模块中的任何代码之前运行)当然你可以向该记录器添加一个处理程序,其格式化程序随你配置,如同给出的示例代码 docs.python.org/library/... 。 - Alex Martelli
谢谢Alex,真的很有帮助!明年我会在PyCon买你一杯啤酒:) - alfredodeza
依靠它的@alfredo - 然后在圣何塞见到你! - ) - Alex Martelli
Pycon本周。我欠你一杯啤酒。你是名人。这会发生吗? :) - alfredodeza


答案:


如果您希望程序包的各个模块中的所有代码都使用相同的记录器对象,您只需要(使该记录器可用 - 请参阅稍后 - 和)调用

mylogger.warning("Attenzione!")

等等,而不是 logging.warning &C。因此,问题减少到制作一个 mylogger 整个包的对象,并使其在包中的整个模块中可用。 (或者,您可以使用名称记录器,其名称以包名称开头,后跟一个点,但是这只是一个部分。 logging 包装功能,我个人从未发现它是一种自然的操作方式)。

所以,你的 util.setlogging 功能可以简单地跟随,比方说,

mylogger = logging.getLogger(package_name)

以及每个进口的模块 util 可以简单地使用

util.mylogger.warning('Watch out!')

等等。在我看来,这似乎是最简单的方法,只要包中的所有代码都应以相同方式登录的概念适用。


11
2017-07-28 00:27



难道我还不需要调用setlogging()来访问'mylogger'吗?即使我尝试了,我仍然得到一个预期的AttributeError,因为'function'对象没有属性'mylogger'。也许我没有完全了解情况...... - alfredodeza
@alfredo,它只需要被调用一次(来自包的 __init__.py 将是最简单的用于此目的的地方,因为你知道它总是在包中的任何模块中的任何代码之前运行)当然你可以向该记录器添加一个处理程序,其格式化程序随你配置,如同给出的示例代码 docs.python.org/library/... 。 - Alex Martelli
谢谢Alex,真的很有帮助!明年我会在PyCon买你一杯啤酒:) - alfredodeza
依靠它的@alfredo - 然后在圣何塞见到你! - ) - Alex Martelli
Pycon本周。我欠你一杯啤酒。你是名人。这会发生吗? :) - alfredodeza


模块使用日志记录的正确方法是

import logging
logger = logging.getLogger('my_module_name')

logger.debug('help!')

在有人打电话之前变成无操作 logging.basicConfig() (或变体)。


1
2017-07-28 00:28