Python模組的動態載入機制
Python在執行環境初始化中,就將sys module載入到了記憶體中,
實際上,Python是將一大批的module載入到了記憶體中。但是為了使local名字空間能夠達到最乾淨的效果,Python並沒有將這些符號暴露在當前的local名字空間中,
而是需要使用者顯式的通過import機制通知Python:需要將這個符號引入到local名字空間中。這些預先被載入進記憶體的module存放在sys.modules中
可以看到os module是從C:\Python25\lib\os.pyc這個檔案中引入的,它是一個內建的module。通過import機制,這個module被引入到了當前的local名字空間。從兩個不同id操作中可以看到,Python虛擬機器的import動作引入的正是事先已經在Python初始化階段被載入到sys.modules集合中的os module。
巢狀import
在usermodule1.py和usermodule2.py中進行的import動作並沒有影響到上一層的名字空間,而只是影響到了各個module自身的名字空間,更準確的說是影響到了各個module自身所維護的那個dict物件。
實際上,所有的import動作都會影響到全域性module集合,即如果程式的另一處再次import這個module,Python虛擬機器只需要將全域性module集合中快取的那個module物件返回即可。
import A.tank
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
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']
不同點:
- import A.tank 在local名稱空間中引入符合"A",並且將其對映到module A
- from A import tank Python虛擬機器在local名稱空間中引入符合"tank",並將其對映到module A.tank
符號重新命名
之前的例子都是通將module自身的名字暴露到了當前的local名稱空間,Python通過as關鍵字可以控制module以什麼名字引入到當前的local名稱空間中。
當前local名稱空間中的Tank實際被對映到了module A.tank。import A.tank 在名稱空間引入的是符號"A",而使用as後,引入的是"Tank",所以當前名稱空間中無法訪問到A了
符號的銷燬與過載
- 符號銷燬
只是刪除了符號"Tank",並沒有真正從sys.modules集合中刪除module
- reload操作
只是向對應的module中新增新的符號,如果有符號在原始檔中被刪除,這種刪除是不會影響到module所維護的dict的。