rei*_*ish 7 python python-module python-2.7 python-internals
我创建了一个带有单个函数的Python模块,只打印'a!'.我打开了Python解释器并用2种不同的语法导入了模块
>>> import a
>>> from a import func
>>> func()
a!
>>> a.func()
a!
Run Code Online (Sandbox Code Playgroud)
此时我更改了func以打印其他内容,然后再次进行评估
>>> func()
a!
>>> a.func()
a!
Run Code Online (Sandbox Code Playgroud)
当然,由于未重新加载模块,因此这是预料之中的.然后我重新加载模块并期望两个函数都更新,但是:
>>> reload(a)
<module 'a' from 'a.py'>
>>> a.func()
aasd!
>>> func()
a!
Run Code Online (Sandbox Code Playgroud)
只有a.func似乎更新.我一直认为Python只保留同一模块的单个实例,但现在似乎有两个.我做了进一步的测试以验证我的声明,并在模块的顶层添加了一个print语句,然后重新启动了解释器并再次导入:
>>> import a
module imported
>>> import a
>>> from a import func
Run Code Online (Sandbox Code Playgroud)
这让我更加困惑,因为我希望看到"模块导入"两次.我做的第三个实验是全局变量实验:
>>> import a
module imported
>>> from a import GLOBAL_VAR
>>> GLOBAL_VAR = 5
>>> a.GLOBAL_VAR
1
>>> GLOBAL_VAR
5
>>> GLOBAL_VAR is a.GLOBAL_VAR
False
Run Code Online (Sandbox Code Playgroud)
所以有一个模块的实例,但内部对象的不同实例?如何用这种行为实现Gevent的猴子修补?
一个模块一旦导入,就只是另一个python对象.因此,看到以下示例,您的结果应该不会让您感到惊讶:
x = SomeObject()
x.y = 1
a = x.y
x.y = 2
print(a) #a is still 1, not 2
Run Code Online (Sandbox Code Playgroud)
当你这样做时from module import name,name会在当前命名空间中创建一个变量,该变量包含对导入的东西的引用(无论是包/模块/类/其他).这是以下的语法糖:
import module
name = module.name
Run Code Online (Sandbox Code Playgroud)
现在,当你重新加载时module,你显然不会更新引用name保持.
关于您的第二个实验,sys.modules导入后会缓存一个模块; 后续导入将利用缓存.因此,直接在模块级别的所有代码(如您的代码print)将仅在第一次导入时执行.