如何在多个模块中使用logging.getLogger(__ name__) [英] How to use logging.getLogger(__name__) in multiple modules

查看:207
本文介绍了如何在多个模块中使用logging.getLogger(__ name__)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

来自 logging howto 对于Python 2.7(我的重点):

命名记录器时要使用的一个很好的约定是使用模块级 记录器,在使用日志记录的每个模块中,命名如下:

logger = logging.getLogger(__name__)

这意味着记录器名称跟踪程序包/模块的层次结构,并且直观地知道仅从记录器名称记录事件的位置.

听起来像个好建议.

现在, logging cookbook 提供了多个模块的示例,这些模块使用硬编码的记录器名称而不是__name__常量.在示例的主模块"中,我们找到了

logger = logging.getLogger('spam_application')

并在辅助模块"中找到

module_logger = logging.getLogger('spam_application.auxiliary')

我将此示例逐字复制到具有以下结构的package文件夹中:

cookbook-example
|- __init__.py
|- main_module.py
|- auxiliary_module.py

这没有问题,可以从主模块和辅助模块中产生预期的日志记录输出,但实际上是这样:

如果我现在按照 1 2 3 5 解决方案

如@shmee在此答案中指出的,必须使用点符号在记录器名称中显式定义记录器层次结构.也就是说,如果main_module.py中的记录器名称为'a',则auxiliary_module.py中的记录器名称必须为'a.b'(而不仅仅是'b'),以便它继承记录器'a'的配置. getLogger()文档中也提到了这一点. >

但是,如此处所述,主模块的__name__将为'__main__'(因为它是顶级脚本),辅助模块的__name__将是'auxiliary_module'(即文件名),而不是'__main__.auxiliary_module'.

因此,辅助模块中的记录器将是根记录器的子级,而不是'__main__'记录器的子级,因此它将继承根记录器配置(仍具有默认的记录级别WARNING),而不是主模块中指定的配置.

因此,为了使示例工作起来,我们有几种选择:

  1. getLogger()替换 main 模块中的getLogger(__name__). 这会将配置应用于根记录器,因此也将其应用于 辅助模块记录器,如@shmee所建议.

  2. 替换辅助模块中的getLogger(__name__),方法是 getLogger('__main__.' + __name__).结果将是等效的 到原始食谱示例(除了现在称主记录器为 '__main__'而不是'spam_application').

From the logging howto for Python 2.7 (my emphasis):

A good convention to use when naming loggers is to use a module-level logger, in each module which uses logging, named as follows:

logger = logging.getLogger(__name__)

This means that logger names track the package/module hierarchy, and it’s intuitively obvious where events are logged just from the logger name.

Sounds like good advice.

Now, the logging cookbook provides an example for multiple modules, which uses hard-coded logger names instead of the __name__ constant. In the "main module" from the example we find

logger = logging.getLogger('spam_application')

and in the "auxiliary module" we find

module_logger = logging.getLogger('spam_application.auxiliary')

I copied this example verbatim into a package folder with the following structure:

cookbook-example
|- __init__.py
|- main_module.py
|- auxiliary_module.py

This runs without issue, producing the expected logging output from both the main module and the auxiliary module, but here's the thing:

If I now replace the hard-coded logger names by the __name__ constant, as recommended by the logging howto, the cookbook example breaks down: I only get logging messages from the main module, but nothing from the auxiliary module.

I must be missing something obvious. Any ideas what I am doing wrong?

Note:

There are a lot of very similar questions and related answers, e.g.: 1, 2, 3, 4, 5, 6, and many more. However, none of those appear to address this specific question.

--Edit--

Here's a minimal example based on the cookbook example, with the explicit name strings replaced by __name__.

main_module.py

import logging
import auxiliary_module

# create and configure main logger
logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG)
# create console handler with a higher log level
handler = logging.StreamHandler()
handler.setLevel(logging.DEBUG)
# create formatter and add it to the handler
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
handler.setFormatter(formatter)
# add the handler to the logger
logger.addHandler(handler)

logger.info('message from main module')
auxiliary_module.some_function()

auxiliary_module.py

import logging

# create logger
module_logger = logging.getLogger(__name__) 

def some_function():
    module_logger.info('message from auxiliary module')

解决方案

As pointed out by @shmee in this answer, the logger hierarchy must be defined explicitly in the logger name, using dot-notation. That is, if the logger name in main_module.py is e.g. 'a', then the logger name in auxiliary_module.py must be 'a.b' (not just 'b'), in order for it to inherit the configuration of logger 'a'. This is also mentioned in the getLogger() documentation.

However, this should be taken care of automatically when using __name__, as noted in the logging how-to:

This means that logger names track the package/module hierarchy, and it’s intuitively obvious where events are logged just from the logger name.

The thing is, for this to work, you need to use __name__ in the correct way, and I did not do that.

The problem in my example is in the organization of the files in the cookbook-example package folder:

Both the main module and the auxiliary module are at the same level (i.e. in the same folder). So, as explained here, the __name__ for the main module will then be '__main__' (as it is the top-level script), and the __name__ for the auxiliary module will be 'auxiliary_module' (i.e. the filename), NOT '__main__.auxiliary_module'.

As a result, the logger in the auxiliary module will be a child of the root logger, not a child of the '__main__' logger, and it will thus inherit the root logger configuration (which still has the default logging level WARNING) instead of the configuration specified in the main module.

So, to make the example work, we have several options:

  1. Replace getLogger(__name__) in the main module by getLogger(). This will apply the config to the root logger and therefore also to the auxiliary module logger, as suggested by @shmee.

  2. Replace getLogger(__name__) in the auxiliary module by getLogger('__main__.' + __name__). The result will be equivalent to the original cookbook-example (except that the main logger is now called '__main__' instead of 'spam_application').

这篇关于如何在多个模块中使用logging.getLogger(__ name__)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆