1. 程式人生 > >Python模組的動態載入機制

Python模組的動態載入機制

Python在執行環境初始化中,就將sys module載入到了記憶體中,
實際上,Python是將一大批的module載入到了記憶體中。但是為了使local名字空間能夠達到最乾淨的效果,Python並沒有將這些符號暴露在當前的local名字空間中,
而是需要使用者顯式的通過import機制通知Python:需要將這個符號引入到local名字空間中。這些預先被載入進記憶體的module存放在sys.modules中

eKiBrKs.png

可以看到os module是從C:\Python25\lib\os.pyc這個檔案中引入的,它是一個內建的module。通過import機制,這個module被引入到了當前的local名字空間。從兩個不同id操作中可以看到,Python虛擬機器的import動作引入的正是事先已經在Python初始化階段被載入到sys.modules集合中的os module。

巢狀import

HvKeFAO.png

在usermodule1.py和usermodule2.py中進行的import動作並沒有影響到上一層的名字空間,而只是影響到了各個module自身的名字空間,更準確的說是影響到了各個module自身所維護的那個dict物件。
實際上,所有的import動作都會影響到全域性module集合,即如果程式的另一處再次import這個module,Python虛擬機器只需要將全域性module集合中快取的那個module物件返回即可。

import A.tank

bsDlNwP.png

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

IH6jccm.png

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

符號重新命名

xT4cuHQ.png

之前的例子都是通將module自身的名字暴露到了當前的local名稱空間,Python通過as關鍵字可以控制module以什麼名字引入到當前的local名稱空間中。
當前local名稱空間中的Tank實際被對映到了module A.tank。import A.tank 在名稱空間引入的是符號"A",而使用as後,引入的是"Tank",所以當前名稱空間中無法訪問到A了

符號的銷燬與過載

  • 符號銷燬
    Rbqz7Y0.png

只是刪除了符號"Tank",並沒有真正從sys.modules集合中刪除module

  • reload操作
    ZRKx0fL.png

只是向對應的module中新增新的符號,如果有符號在原始檔中被刪除,這種刪除是不會影響到module所維護的dict的。