跨多个模块记录如何工作?

时间:2018-08-08 17:28:51

标签: python python-3.x logging module

根据logging模块的cookbook

  

使用多个模块中的日志记录

     

多次调用logging.getLogger('someLogger')将返回对同一记录器对象的引用。只要在同一Python解释器进程中,不仅在同一模块内,而且在各个模块之间都是如此。引用同一对象是正确的。此外,应用程序代码可以在一个模块中定义和配置父记录器,并在单独的模块中创建(但不配置)子记录器,并且对子记录器的所有调用都将传递给父记录器。

这是如何工作的? (我尝试查看模块源代码,但无法弄清楚。)到目前为止,我还不知道我可以定义跨模块可访问的“超全局”对象。 为了帮助我理解logging的工作方式,您能否告诉我如何使以下工作正常进行:

foo.py中,做

import my_module

my_module.set_my_value(42)

并在“ bar.py”中执行

import my_module

print(my_module.get_my_value())  # Should print 42

1 个答案:

答案 0 :(得分:1)

首先,做您想做的事是微不足道的。当您import使用某个模块时,只有import的其他任何人共享该模块对象的一个​​实例, 1 ,并且该模块对象的属性只是该模块的全局变量。所以:

# script.py
import cheese
import eggs
cheese.beans = 10
eggs.dostuff()

# eggs.py
import cheese
print(cheese.beans)
print(cheese.ham)

# cheese.py
ham = 20

如果运行script.py,它将打印10,然后是20。

您当然必须注意顶层模块代码,该代码按模块首次导入的顺序运行(可能很难解决), 2 和代码 3 ,但在其他情况下,它可以正常工作,而无需任何特殊的getter和setter函数。

(如果出于某种原因需要getter和setter函数,则适用于任何对象的相同getattrsetattr在模块对象上也可以正常工作。)

现在,logging如何发挥其魔力?简单;它只是在其全局变量中存储字典。由于模块只有一个实例,因此它的全局变量也只有一个实例,因此字典也只有一个实例。


1。如果您想了解 的工作原理……执行import cheese时,Python会做什么(默认情况下,假设您未安装任何怪异的导入挂钩)是:首先,有sys.modules['cheese']吗?如果不是,请找到cheese的规范,使用它来查找加载程序,使用加载程序加载代码,exec代码,并将结果存储为sys.modules['cheese']。然后只需return sys.modules['cheese']。这就是为什么每个模块只让其顶级代码运行一次的原因,无论您import进行了多少次,这也是为什么import的每个模块都共享同一模块对象副本的原因。

2。您的示例仅适用于my_module.my_value = 42print(my_module.myvalue)-如果fooimport之前得到bar。但是,如果bar首先获得import,它将得到一个AttributeError,因为显然还没有人设置my_module.my_value

3。主要原因是,当您运行script.py时,它不是作为名为script的模块运行,而是作为名为__main__的模块运行。这就是if __name__ == '__main__':后卫成语起作用的原因。但是,如果其他人执行import script,则script不在sys.modules中,因此Python将加载并执行具有自己的全局变量的script.py的单独副本。 / sub>