根据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
答案 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函数,则适用于任何对象的相同getattr
和setattr
在模块对象上也可以正常工作。)
现在,logging
如何发挥其魔力?简单;它只是在其全局变量中存储字典。由于模块只有一个实例,因此它的全局变量也只有一个实例,因此字典也只有一个实例。
1。如果您想了解 的工作原理……执行import cheese
时,Python会做什么(默认情况下,假设您未安装任何怪异的导入挂钩)是:首先,有sys.modules['cheese']
吗?如果不是,请找到cheese
的规范,使用它来查找加载程序,使用加载程序加载代码,exec
代码,并将结果存储为sys.modules['cheese']
。然后只需return sys.modules['cheese']
。这就是为什么每个模块只让其顶级代码运行一次的原因,无论您import
进行了多少次,这也是为什么import
的每个模块都共享同一模块对象副本的原因。
2。您的示例仅适用于my_module.my_value = 42
和print(my_module.myvalue)
-如果foo
在import
之前得到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>