Python 难以理解 getLogger(__name__)

问题描述 投票:0回答:1

我对日志文档对

getLogger(__name__)
作为最佳实践的解释感到非常困惑。

将解释我的整个思考过程,如有错误,请随时发表评论

日志文档

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

logger = logging.getLogger(__name__)

假设我有一个项目结构:

main_module.py
cookbook_example
---auxiliary_module.py

主模块.py

import logging
from cookbook_example import auxiliary_module
# Creates a new logger instance
logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG)
# Create file handler that logs debug messages
fh = logging.FileHandler('spam.log', mode='w')
fh.setLevel(logging.DEBUG)
# Create a formatter
formatter = logging.Formatter(
    '%(asctime)s - %(name)s - %(levelname)s - %(message)s')
fh.setFormatter(formatter)
logger.addHandler(fh)

logger.info('Creating instance of auxiliary_module.Auxiliary')
a = auxiliary_module.Auxiliary()
logger.info('Calling auxiliary_module.do_something')
a.do_something()
auxiliary_module.some_function()

辅助模块.py

import logging

# create logger
module_logger = logging.getLogger(f'__main__.{__name__}')


def some_function():
    module_logger.info('received a call to "some_function"')

现在,从这个SO线程,我推断

getLogger(__name__)
实际上不应该在每个使用日志记录的模块中使用,而应该在配置记录器的模块中使用,在这种情况下将是main_module.py

例如在辅助模块中,尝试通过

getLogger(__name__)
获取自定义记录器将返回根记录器,而
getLogger(f'__main__.{__name__}')
将返回该自定义记录器。

对我来说,

getLogger(f'__main__.{__name__}')
的这种格式似乎并不比显式的
getLogger('main_module.auxiliary_module')
更容易编写。此外,在日志文件中,它记录的是
__main__.auxiliary_module
而不是
main_module.auxiliary_module
,因此失去了一点准确性。

最后,我之前说过,根据我的理解,

getLogger(__name__)
只能放置在配置记录器的模块中。但是,无论如何,配置都应该放在配置文件或字典中。

因此,我似乎不理解

getLogger(__name__)
的任何合理用法以及根据文档,它是如何成为最佳实践的。有人可以解释一下这一点,也许可以链接一个使用记录器的存储库和我可以参考的正确组织吗?谢谢

python logging
1个回答
7
投票

假设这个简单的项目:

project/
├── app.py
├── core
│   ├── engine.py
│   └── __init__.py
├── __init__.py
└── utils
    ├── db.py
    └── __init__.py

哪里

app.py
是:

import logging
import sys

from utils import db
from core import engine

logger = logging.getLogger()
logger.setLevel(logging.INFO)
stdout = logging.StreamHandler(sys.stdout)
stdout.setFormatter(logging.Formatter("%(name)s: %(message)s"))
logger.addHandler(stdout)


def run():
    db.start()
    engine.start()


run()

utils/db.py
core/engine.py
是:

from logging import getLogger

print(__name__)  # will print utils.db or core.engine
logger = getLogger(__name__)
print(id(logger))  # different object for each module; child of root though


def start():
    logger.info("started")

如果您使用

python app.py
运行此命令,您将看到它会为您打印 proper 命名空间。

utils.db: started
core.engine: started

如果您的代码组织良好,那么您的模块名称本身就是可用的最佳记录器名称。如果您必须重新命名这些名称,通常意味着您的模块结构很糟糕(或某些特殊的、 非标准用例)。但对于大多数用途来说,这应该可以正常工作(因此是 stdlib 的一部分)。

仅此而已。请记住,您并没有真正为 libraries 设置 handlers;这是留给消费者的。

© www.soinside.com 2019 - 2024. All rights reserved.