Python包中用__name__配置Logger遇__main__问题及相关疑问
我的Python包结构如下:
test_script.py package_name/ __init__.py functionality_1.py functionality_2.py
为了测试调试,我在functionality_1.py末尾添加了标准的main代码块:
if __name__ == "__main__": # 执行测试逻辑
我希望functionality_1.py的日志使用logger名称package_name.functionality_1,functionality_2.py使用package_name.functionality_2。尝试用logger = logging.getLogger(__name__)配置,但用python -m package_name.functionality_1运行时,logger名称始终为__main__。我不想硬编码logger名称,想了解如何正确创建各模块专属logger,以及在包文件中添加main函数是否属于不良规范。
一、正确创建模块专属Logger的方法
用python -m package_name.functionality_1运行模块时,__name__会被设为__main__,这是Python的正常行为。要获取模块的真实名称,可以用以下两种方案解决:
方法1:利用__package__属性构建名称
在functionality_1.py中这样编写:
import logging # 拼接出模块的真实名称 module_name = f"{__package__}.{__name__.split('.')[-1]}" if __package__ else __name__ logger = logging.getLogger(module_name)
当以-m方式运行时,__package__会被自动设为package_name,结合__name__的最后一部分,就能得到package_name.functionality_1;如果模块是被其他代码导入,__name__本身就是package_name.functionality_1,此时也能正确匹配。
方法2:从sys.modules中获取真实名称
Python会把已加载的模块存放在sys.modules字典中,可以直接从中读取模块的真实标识:
import logging import sys # 获取当前模块的真实名称 current_module = sys.modules[__name__] if current_module.__package__: real_module_name = f"{current_module.__package__}.{current_module.__name__.split('.')[-1]}" else: real_module_name = current_module.__name__ logger = logging.getLogger(real_module_name)
这种方式更稳妥,能直接拿到模块在Python导入系统中的真实名称。
二、包模块中添加main函数是否属于不良规范?
这不仅不是不良规范,反而属于推荐做法:
- 可以快速测试模块功能,无需额外编写独立测试脚本;
- 开发阶段能直接通过
python -m package_name.functionality_1验证模块逻辑; - 符合Python“可执行模块”的设计理念,很多官方库和成熟第三方库都会在模块中添加
if __name__ == "__main__"块用于测试或快速演示。
不过需要注意几个细节:
- main块内的代码应仅用于测试、演示逻辑,不要包含模块核心功能的初始化代码,避免被其他模块导入时意外执行;
- 可以把测试逻辑封装成独立函数,在main块中调用,保持代码整洁;
- 如果测试逻辑复杂,建议拆分到专门的
tests/目录,但模块内的简单测试main块依然有实用价值。
内容的提问来源于stack exchange,提问作者bpeikes

