我对日志文档对
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__)
的任何合理用法以及根据文档,它是如何成为最佳实践的。有人可以解释一下这一点,也许可以链接一个使用记录器的存储库和我可以参考的正确组织吗?谢谢
假设这个简单的项目:
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;这是留给消费者的。