![](/img/trans.png)
[英]Python logging - config file in multiple modules with root logger
[英]Logger hierarchy and the root logger when logging with multiple modules
我有这个设置:
main.py
/module
/module/__init__.py (empty)
/module.py
这是我的两个文件main.py
和module.py
的代码:
主文件
import logging
from module import module
logger = logging.getLogger(__name__)
def test():
logger.warning('in main.py/test')
def main():
handler = logging.StreamHandler()
handler.setLevel(logging.INFO)
formatter = logging.Formatter('%(asctime)s %(name)s/%(module)s [%(levelname)s]: %(message)s', '%Y-%m-%d %H:%M:%S')
handler.setFormatter(formatter)
logger.addHandler(handler)
logger.warning('in main.py/main')
module.something()
if __name__ == "__main__":
main()
模块.py
import logging
logger = logging.getLogger(__name__)
def something():
logger.warning('in module.py/something')
所以,我注意到它输出以下内容(注意模块记录器如何没有格式):
2019-10-01 09:03:40 __main__/main [WARNING]: in main.py/main
in module.py/something
似乎只有在我在main.py
中进行编辑以将logger = logging.getLogger( __ name __ )
更改为logger = logging.getLogger()
或在def main():
) 之后添加logger = logging.getLogger()
之后:它像这样记录(这是我想要的):
2019-10-01 09:04:13 root/main [WARNING]: in main.py/main
2019-10-01 09:04:13 module.module/module [WARNING]: in module.py/something
这是为什么? 我认为因为main.py
正在导入module.py
,所以它在层次规模上自然更高,因此module.py
将继承main.py
中定义的记录器设置。 是否需要在 main 中显式设置根记录器(使用logger = logging.getLogger()
)才能使 inheritance 正常工作? 我没有正确配置我的文件夹结构以使module.py
的记录器继承main.py
的记录器设置,还是文件夹结构无关紧要?
我问的原因是因为我认为应该始终使用logger = logging.getLogger( __ name __ )
(甚至在main.py
中),然后根据导入结构(或文件夹结构?),这将确定层次结构和记录器会相应地继承。 我做出这个假设的原因是因为如果我将main.py
导入另一个程序会怎样? 我想我的意思是,我想让日志记录尽可能通用,这样我就可以将一个模块导入另一个模块,并且它总是继承父级的记录器设置。 有没有办法显示所有模块的底层层次结构以进行调试/学习?
日志层次结构与程序中的文件结构无关。 层次结构仅由记录器的名称确定。 当您配置一个记录器时,除非另有明确说明,否则名称前缀中的所有记录器都是其子级并继承其配置。
在您的示例中,日志记录设置更多地与执行顺序和您选择的名称有关。 当您的程序运行时,它会执行以下操作:
import logging
,从标准库运行logging.py
module.py
以实现from module import module
main
中的logger
属性设置为名为__main__
的Logger
。test
functionmain
function这一系列事件的一些后果:
module.logger
在main.logger
之前创建。 这不会影响您看到的行为,但在这种情况下值得注意。main
作为脚本调用,则main.logger
被命名为__main__
。 如果它被称为main
,您看到的行为不会改变,例如从python -m main
。module
显然与main
不在同一层次结构中。 两者都是沿不同分支的根记录器的后代。最后一项确实是您问题的答案。 如果您希望程序中的所有记录器共享相同的默认记录方法,则应配置根记录器,或确保它们具有相同的名称前缀,然后将其配置为就像它是根记录器一样。
您可以让所有记录器从main
继承。 在module/module.py
,你会做
logger = logging.getLogger('__main__.' + __name__)
这里的问题是名称__main__
是硬编码的。 您不能保证它将是__main__
与main
。 你可以尝试import main
in module
这样你就可以做main.__name__ + '.' + __name__
main.__name__ + '.' + __name__
,但这不会按预期工作。 如果main
作为__main__
运行,导入它实际上将创建第二个模块 object 具有完全独立的日志记录层次结构。
这就是根记录器没有名称的原因。 它提供了您想要的可维护性和一致性。 您不必为了找出根名称而费尽心思。
话虽如此,您仍然应该将main.py
记录到__main__
或main
记录器。 根记录器只能在导入防护中设置。 这样,如果main
作为常规模块导入,它将尊重正在运行的驱动程序的日志记录设置。
TL;博士
通常在程序的驱动程序中设置匿名根记录器。 不要尝试从__main__
或驱动程序模块名称继承记录器。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.