我有这样的设置:
main.py
/module
/module/__init__.py (empty)
/module.py
下面是我的两个文件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
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
中定义的记录器设置。是否需要显式设置主根记录器(使用logger = logging.getLogger()
)才能使继承工作?我是否没有正确配置我的文件夹结构,使module.py
的记录器继承main.py
的记录器设置,还是文件夹结构无关?
我之所以问这个问题,是因为我认为应该在整个过程中使用logger = logging.getLogger( __ name __ )
(甚至在main.py
中),然后基于导入结构(或文件夹结构?)来确定层次结构和记录器将相应继承。我之所以做出这样的假设,是因为如果我将main.py
导入到另一个程序中怎么办?我想我的观点是,我想使日志记录尽可能通用,这样我就可以将一个模块导入另一个模块,并且它总是继承父模块的记录器设置。是否有方法显示所有模块的底层层次结构,以便进行调试/学习?
发布于 2019-10-04 06:20:06
日志层次结构与程序中的文件结构无关。层次结构仅由记录器的名称确定。配置记录器时,所有其名称前缀为其名称的记录器都是其子程序,除非另有明确说明,否则将继承其配置。
在您的示例中,日志设置更多地与执行顺序和您所选择的名称有关。当程序运行时,它会执行以下操作:
由于import logging
module.py
,logging.py
,以实现main
中的logger
属性,并命名为__main__
.test
functionmain
函数H 220H 121
运行主函数H 222G 223
这一系列事件的一些后果:
module.logger
是在main.logger
之前创建的。这并不影响您所看到的行为,但是如果您将circumstances.main.logger
作为脚本调用main
,则在main
是命名为main
的情况下值得注意。如果您看到的行为称为main
,则行为不会改变,例如,来自main
的行为显然与main
的层次结构不同。它们都是根记录器在不同分支上的后代。最后一项确实是你问题的答案。如果希望程序中的所有记录器共享相同的默认日志记录方法,则应配置根记录器,或确保它们具有相同的名称前缀,然后将其配置为根日志记录器。
您可以让所有记录器从main
继承。在module/module.py
中,您可以
logger = logging.getLogger('__main__.' + __name__)
这里的问题是名称__main__
是硬编码的。您无法保证这将是__main__
对main
。您可以尝试在import main
中使用module
,这样就可以执行main.__name__ + '.' + __name__
,但这不能像预期的那样工作。如果main
作为__main__
运行,导入它实际上将创建第二个模块对象,该对象具有完全独立的日志层次结构。
这就是根记录器没有名称的原因。它提供了所需的可维护性和一致性。你不需要跳过圈试图找出根的名称。
尽管如此,您仍然应该将main.py
日志记录到__main__
或main
记录器。根记录器只应在导入保护中设置。这样,如果将main
作为常规模块导入,它将尊重正在运行的驱动程序的日志记录设置。
TL;博士
传统的做法是在程序的驱动程序中设置匿名根记录器。不要试图从__main__
或驱动程序模块名继承记录器。
https://stackoverflow.com/questions/58188743
复制相似问题