Python从config.py导入变量的底层逻辑:__init__.py的影响
Python包中config模块共享变量的import逻辑疑问
我是Python新手,正在理解config.py模块如何在包的各模块间共享变量。查阅资料后,我对import的底层机制已有一定了解,但仍对__init__.py隐式参与时from...import的运行逻辑存在疑问。
示例包结构
test/ __init__.py from test import config config.username = "username-init" config.py username = "username-config" mainthing.py from test import config print(config.username)
运行import mainthing后,输出结果为username-init。我的疑问是:mainthing.py为何能获取到__init__.py修改后的config.username值?
我梳理的运行流程如下:
mainthing.py执行from test import config时,会先运行test包的__init__.py;__init__.py执行from test import config,将config.py导入自身命名空间,随后修改config.username为"username-init";mainthing.py继续执行from test import config,此时为何导入的是__init__.py中已修改的config实例,而非config.py原有的值?我困惑的是,当__init__.py已加载config后,mainthing.py的import是否直接复用了该实例,而非重新加载config.py?
问题解答
核心原因是Python模块是单例模式,且导入后会被全局缓存:
- 当
__init__.py执行from test import config时,Python会加载test.config模块,将其实例存入全局缓存字典sys.modules(键为'test.config'),同时把这个模块实例的引用添加到test包的命名空间中(__init__.py的执行过程就是在构建包的命名空间)。 __init__.py修改config.username,本质是直接修改了sys.modules['test.config']这个模块实例的属性——模块对象是可变的,这个修改会永久作用在缓存的实例上。- 当
mainthing.py执行from test import config时,Python会先检查test包的命名空间,发现已经存在config引用(指向缓存的test.config模块实例),于是直接返回这个引用,不会重新加载config.py。
换句话说:整个Python进程中,同一个模块只会被加载一次,所有导入操作拿到的都是同一个模块对象。__init__.py先修改了这个对象的属性,后续任何地方导入该模块,都会看到修改后的值。
内容的提问来源于stack exchange,提问作者Jones Smith
相关产品推荐
相关产品推荐

