[英]Logger hierarchy and the root logger when logging with multiple modules
I have this setup:我有这个设置:
main.py
/module
/module/__init__.py (empty)
/module.py
And here is the code for my two files, main.py
and module.py
respectively:这是我的两个文件
main.py
和module.py
的代码:
main.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()
module.py模块.py
import logging
logger = logging.getLogger(__name__)
def something():
logger.warning('in module.py/something')
So, what I noticed is that this outputs the following (notice how the module logger has no formatting):所以,我注意到它输出以下内容(注意模块记录器如何没有格式):
2019-10-01 09:03:40 __main__/main [WARNING]: in main.py/main
in module.py/something
It only seems like only after I make an edit in main.py
to change logger = logging.getLogger( __ name __ )
to logger = logging.getLogger()
or add logger = logging.getLogger()
after def main():
that it logs like this (which is what I want):似乎只有在我在
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
Why is that?这是为什么? I thought that because
main.py
is importing module.py
, it is naturally higher on the hierarchical scale so module.py
would inherit the logger settings as defined in main.py
.我认为因为
main.py
正在导入module.py
,所以它在层次规模上自然更高,因此module.py
将继承main.py
中定义的记录器设置。 Do need to explicitly set the root logger (with logger = logging.getLogger()
) in main for the inheritance to work?是否需要在 main 中显式设置根记录器(使用
logger = logging.getLogger()
)才能使 inheritance 正常工作? Did I not configure my folder structure correctly to make module.py
's logger inherit main.py
's logger settings, or is folder structure irrelevant?我没有正确配置我的文件夹结构以使
module.py
的记录器继承main.py
的记录器设置,还是文件夹结构无关紧要?
The reason I ask is because I thought one should use logger = logging.getLogger( __ name __ )
throughout (even in main.py
) and then based on the import structure (or folder structure?), that would determine the hierarchy and loggers would inherit accordingly.我问的原因是因为我认为应该始终使用
logger = logging.getLogger( __ name __ )
(甚至在main.py
中),然后根据导入结构(或文件夹结构?),这将确定层次结构和记录器会相应地继承。 And the reason I was making that assumption is because what if I was importing main.py
into another program?我做出这个假设的原因是因为如果我将
main.py
导入另一个程序会怎样? I guess my point is, I want to make logging as generic as possible such that I can import one module into another and it always inherits the parent's logger settings.我想我的意思是,我想让日志记录尽可能通用,这样我就可以将一个模块导入另一个模块,并且它总是继承父级的记录器设置。 Is there a way to display the underlying hierarchy of all the modules for debugging/learning purposes?
有没有办法显示所有模块的底层层次结构以进行调试/学习?
The logging hierarchy has nothing to do with file structure in your program.日志层次结构与程序中的文件结构无关。 The hierarchy is determined only by the names of the loggers.
层次结构仅由记录器的名称确定。 When you configure a logger, all loggers with its name in the prefix of their name are its children and inherit its configuration unless explicitly stated otherwise.
当您配置一个记录器时,除非另有明确说明,否则名称前缀中的所有记录器都是其子级并继承其配置。
In your example, logging setup has more to do with execution sequence and the names you've chosen than anything else.在您的示例中,日志记录设置更多地与执行顺序和您选择的名称有关。 When your program runs, it does the following:
当您的程序运行时,它会执行以下操作:
logging.py
from the standard library because of import logging
import logging
,从标准库运行logging.py
module.py
to fulfill from module import module
module.py
以实现from module import module
logger
attribute in main
to a Logger
named __main__
.main
中的logger
属性设置为名为__main__
的Logger
。test
functiontest
functionmain
functionmain
function Some consequences of this sequence of events:这一系列事件的一些后果:
module.logger
is created before main.logger
. module.logger
在main.logger
之前创建。 This doesn't affect the behavior you're seeing, but it's worth noting under the circumstances.main.logger
is named __main__
if you invoke main
as a script.main
作为脚本调用,则main.logger
被命名为__main__
。 The behavior you see wouldn't change if it was called main
, eg from python -m main
.main
,您看到的行为不会改变,例如从python -m main
。module
is clearly not in the same hierarchy as main
. module
显然与main
不在同一层次结构中。 Both are descendants of the root logger along different branches. The last item is really the answer to your question.最后一项确实是您问题的答案。 If you want all the loggers in your program to share the same default logging method, you should configure the root logger, or ensure that they have the same name prefix, which you then configure as if it was the root logger.
如果您希望程序中的所有记录器共享相同的默认记录方法,则应配置根记录器,或确保它们具有相同的名称前缀,然后将其配置为就像它是根记录器一样。
You could make all the loggers inherit from main
.您可以让所有记录器从
main
继承。 In module/module.py
, you would do在
module/module.py
,你会做
logger = logging.getLogger('__main__.' + __name__)
The issue here is that the name __main__
is hard coded.这里的问题是名称
__main__
是硬编码的。 You don't have a guarantee that it will be __main__
vs main
.您不能保证它将是
__main__
与main
。 You could try import main
in module
so you could do main.__name__ + '.' + __name__
你可以尝试
import main
in module
这样你就可以做main.__name__ + '.' + __name__
main.__name__ + '.' + __name__
, but that wouldn't work as expected. main.__name__ + '.' + __name__
,但这不会按预期工作。 If main
was run as __main__
, importing it will actually create a second module object with an entirely separate logging hierarchy.如果
main
作为__main__
运行,导入它实际上将创建第二个模块 object 具有完全独立的日志记录层次结构。
This is why the root logger has no name.这就是根记录器没有名称的原因。 It provides exactly the maintainability and consistency you want.
它提供了您想要的可维护性和一致性。 You don't have to jump through hoops trying to figure out the root name.
您不必为了找出根名称而费尽心思。
That being said, you should still have main.py
logging to the __main__
or main
logger.话虽如此,您仍然应该将
main.py
记录到__main__
或main
记录器。 The root logger should only be set up in the import guard.根记录器只能在导入防护中设置。 That way, if
main
is imported as a regular module, it will respect the logging setup of the driver it is running under.这样,如果
main
作为常规模块导入,它将尊重正在运行的驱动程序的日志记录设置。
TL;DR TL;博士
It is conventional to set up the anonymous root logger in the driver of your program.通常在程序的驱动程序中设置匿名根记录器。 Don't try to inherit loggers from
__main__
or the driver module name.不要尝试从
__main__
或驱动程序模块名称继承记录器。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.