从Python 2.7的logginghowto(我的重点):
logging
命名记录器时,一个好的习惯是在每个使用日志记录的模块中使用模块级记录器,命名如下: logger = logging.getLogger(__name__) 这意味着记录器名称跟踪包/模块的层次结构 ,并且从记录器名称中记录事件的地方就很明显了。
命名记录器时,一个好的习惯是在每个使用日志记录的模块中使用模块级记录器,命名如下:
logger = logging.getLogger(__name__)
这意味着记录器名称跟踪包/模块的层次结构 ,并且从记录器名称中记录事件的地方就很明显了。
听起来像个好建议。
现在,本logging手册为多个模块提供了一个示例,该示例使用硬编码的记录器名称而不是__name__常量。在示例的“主模块”中,我们发现
__name__
logger = logging.getLogger('spam_application')
在“辅助模块”中
module_logger = logging.getLogger('spam_application.auxiliary')
我将此示例逐字复制到具有以下结构的package文件夹中:
cookbook-example |- __init__.py |- main_module.py |- auxiliary_module.py
这没有问题,可以从主模块和辅助模块产生预期的日志记录输出,但是事情是这样的:
如果现在__name__按照logginghowto的建议,用常数替换硬编码的记录器名称,则本食谱示例将崩溃:我仅从主模块获取记录消息,而从辅助模块中获取不到任何消息。
我肯定想念一些明显的东西。有什么想法我做错了吗?
- 编辑 -
这是一个基于Cookbook示例的最小示例,显式名称字符串替换为__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()
assistant_module.py
import logging # create logger module_logger = logging.getLogger(__name__) def some_function(): module_logger.info('message from auxiliary module')
正如@shmee在此答案中指出的那样,必须在记录器名称中使用点符号显式定义记录器层次结构。也就是说,如果in中的记录器名称main_module.py为'a',则in的记录器名称auxiliary_module.py必须为'a.b'(而不仅仅是'b'),以便它继承logger的配置'a'。getLogger()文档中也提到了这一点。
'a'
auxiliary_module.py
'a.b'
'b'
getLogger()
然而,这应该会自动使用时的照顾__name__,如在提到logging如何做:
这意味着记录器名称跟踪程序包/模块的层次结构,并且从记录器名称中记录事件的地方就很明显了。
问题是,要使其正常工作,您需要以__name__正确的方式使用,而我没有这样做。
我的示例中的问题在于cookbook-examplepackage文件夹中文件的组织:
cookbook-example
主模块和辅助模块都处于同一级别(即,在同一文件夹中)。所以,作为解释这里的__name__主模块将是'__main__'(因为它是顶级脚本),以及__name__用于辅助模块会'auxiliary_module'(即文件名),NOT '__main__.auxiliary_module'。
'__main__'
'auxiliary_module'
'__main__.auxiliary_module'
结果,辅助模块中的logger将是root logger的子级,而不是logger的子级'__main__',因此它将继承root logger配置(仍具有默认的日志记录级别WARNING),而不是在中指定的配置。主模块。
WARNING
因此,为使示例正常工作,我们有几种选择:
更换getLogger(__name__)中 主要 的模块getLogger()。如@shmee所建议的那样,这会将配置应用于根记录器,从而也应用于辅助模块记录器。
getLogger(__name__)
替换getLogger(__name__)中 辅助 由模块 getLogger('__main__.' + __name__)。结果将与原始食谱示例相同(除了现在调用主记录器 '__main__'代替'spam_application')。
getLogger('__main__.' + __name__)
'spam_application'