Python模块的动态加载机制

Python在运行环境初始化中,就将sys module加载到了内存中,

实际上,Python是将一大批的module加载到了内存中。但是为了使local名字空间能够达到最干净的效果,Python并没有将这些符号暴露在当前的local名字空间中,

而是需要用户显式的通过import机制通知Python:需要将这个符号引入到local名字空间中。这些预先被加载进内存的module存放在sys.modules中

Python模块的动态加载机制

可以看到os module是从C:\Python25\lib\os.pyc这个文件中引入的,它是一个内建的module。通过import机制,这个module被引入到了当前的local名字空间。从两个不同id操作中可以看到,Python虚拟机的import动作引入的正是事先已经在Python初始化阶段被加载到sys.modules集合中的os module。

嵌套import

Python模块的动态加载机制

在usermodule1.py和usermodule2.py中进行的import动作并没有影响到上一层的名字空间,而只是影响到了各个module自身的名字空间,更准确的说是影响到了各个module自身所维护的那个dict对象。

实际上,所有的import动作都会影响到全局module集合,即如果程序的另一处再次import这个module,Python虚拟机只需要将全局module集合中缓存的那个module对象返回即可。

import A.tank

Python模块的动态加载机制

import之前的名称空间: ['__builtins__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__']
import之后的名称空间: ['A', '__builtins__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__']
A的local名称空间 ['__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__path__', '__spec__', 'tank']

from A import tank

Python模块的动态加载机制

import之前的名称空间: ['__builtins__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__']
import之后的名称空间: ['__builtins__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'tank']

import A.tank与from A import tank的区别:

相同点:

两者都将A.tank module以及A作为moudle添加到sys.modules集合中

sys.modules['A']

sys.modules['A.tank']

不同点:

  1. import A.tank 在local名称空间中引入符合"A",并且将其映射到module A
  2. from A import tank Python虚拟机在local名称空间中引入符合"tank",并将其映射到module A.tank

符号重命名

Python模块的动态加载机制

之前的例子都是通将module自身的名字暴露到了当前的local名称空间,Python通过as关键字可以控制module以什么名字引入到当前的local名称空间中。

当前local名称空间中的Tank实际被映射到了module A.tank。import A.tank 在名称空间引入的是符号"A",而使用as后,引入的是"Tank",所以当前名称空间中无法访问到A了

符号的销毁与重载

  • 符号销毁

    Python模块的动态加载机制

只是删除了符号"Tank",并没有真正从sys.modules集合中删除module

  • reload操作

    Python模块的动态加载机制

只是向对应的module中添加新的符号,如果有符号在源文件中被删除,这种删除是不会影响到module所维护的dict的。

上一篇:Spring怎么引入多个xml配置文件


下一篇:wpf 绑定中的数学逻辑运算,可做到Path的加减乘除,用于适配界面的大小,再也不用写死图标的大小了