1. 程式人生 > >python中的import詳解

python中的import詳解

標準的匯入模組

在python中所有載入到記憶體中的模組都存在於sys.modules

當 import 一個模組時首先會在這個列表中查詢是否已經載入了此模組:

如果載入了則只是將模組的名字加入到正在呼叫 import 的模組的 Local 名字空間中。

如果沒有載入則從 sys.path 目錄中按照模組名稱查詢模組檔案,模組可以是py、pyc、pyd,找到後將模組載入記憶體,並加到 sys.modules 中,

並將名稱匯入到當前的 Local名字空間
一個模組不會重複載入。多個不同的模組都可以用 import 引入同一個模組到自己的 Local 名字空間,其實背後的 PyModuleObject 物件只有一個。

注意

  • import匯入為絕對匯入
  • import 只能匯入模組,不能匯入模組中的物件(類、函式、變數等)

巢狀import

順序巢狀

例如:本模組匯入 A 模組(import A),A 中又 import B,B 模組又可以 import 其他模組……
注意:各個模組的 Local 名字空間是獨立的

對於上面的例子,本模組 import A 之後本模組只能訪問模組 A,不能訪問模組 B 及其他模組。雖然模組 B 已經載入到記憶體了,如果訪問還要再明確的在本模組中 import B。

迴圈巢狀

例如:檔案[ A.py ]
                   from B import D
                   class C:pass


                   檔案[ B.py ]
                   from A import C
                   class D:pass

 為什麼執行 A 的時候不能載入 D 呢?
 如果將 A.py 改為:import B 就可以了。
 這是怎麼回事呢?


 RobertChen:這跟Python內部 import 的機制是有關的,具體到 from B import D,Python 內部會分成幾個步驟:
        (1)在 sys.modules 中查詢符號 “B”
        (2)如果符號 B 存在,則獲得符號 B 對應的 module 物件。
                從 <modult B> 的 __dict__ 中獲得符號 “D” 對應的物件,如果 “D” 不存在,則丟擲異常。
        (3)如果符號 B 不存在,則建立一個新的 module 物件 <module B>,注意,此時,module 物件的 __dict__ 為空。
                執行 B.py 中的表示式,填充 <module B> 的 __dict__。
                從  <module B> 的 __dict__ 中獲得 “D” 對應的物件,如果 “D” 不存在,則丟擲異常。


          所以這個例子的執行順序如下:
          1、執行 A.py 中的 from B import D 由於是執行的 python A.py,所以在 sys.modules 中並沒有 <module B> 存在, 首先為 B.py 建立一個 module 物件 (<module B>) , 注意,這時建立的這個 module 物件是空的,裡邊啥也沒有, 在 Python 內部建立了這個 module 物件之後,就會解析執行 B.py,其目的是填充 <module B> 這個 __dict__。
          2、執行 B.py中的from A import C 在執行B.py的過程中,會碰到這一句,首先檢查sys.modules這個module快取中是否已經存在<module A>了, 由於這時快取還沒有快取<module A>,所以類似的,Python內部會為A.py建立一個module物件(<module A>), 然後,同樣地,執行A.py中的語句
          3、再次執行A.py中的from B import D 這時,由於在第1步時,建立的<module B>物件已經快取在了sys.modules中,所以直接就得到了<module B>,但是,注意,從整個過程來看,我們知道,這時<module B>還是一個空的物件,裡面啥也沒有, 所以從這個module中獲得符號"D"的操作就會丟擲異常。如果這裡只是import B,由於"B"這個符號在sys.modules中已經存在,所以是不會丟擲異常的。

包 import

       只要一個資料夾下面有個 __init__.py 檔案,那麼這個資料夾就可以看做是一個包

包匯入的過程和模組的基本一致,只是匯入包的時候會執行此包目錄下的 __init__.py 而不是模組裡面的語句了。

如果只是單純的匯入包,而包的 __init__.py 中又沒有明確的其他初始化操作,那麼此包下面的模組是不會自動匯入的

原文地址:http://blog.sina.com.cn/s/blog_90bc5fc6010159e0.html