URLhttps://learnscript.net/zh-hant/python-reference/modules/
    複製連結移至說明  範例

    Python 模組完整名稱,模組快取介紹

    閱讀 7:56·字數 2382·發佈 
    Youtube 頻道
    訂閱 375

    本節所講述的內容,並不完全適用於通過類別ModuleType動態建立的模組型別物件。

    Python 模組的完整名稱

    Python 模組的完整名稱,可以讓模組被匯入系統正確的搜尋到,因此,完整名稱一般需要根據模組搜尋路徑來確定。

    當模組對應的py檔案或pyc位元組碼檔案,或套件對應的資料夾,位於模組搜尋路徑的任意目錄中時,模組或套件的名稱就是其完整名稱。否則,完整名稱應使用.拼接模組或套件所在的父級套件的名稱,這一過程將重複,直至某個父級套件位於模組搜尋路徑的任意目錄。

    模組的完整名稱類似於檔案系統中的路徑

    在完整名稱中包含父級套件的名稱,是合情合理的,因為 Python 套件具有命名空間的效果。而大部分情況下,套件與資料夾對應,因此,完整名稱的表現方式類似於檔案系統的路徑。

    模組的完整名稱可能會發生變化

    當模組搜尋路徑改變時,模組的完整名稱可能會發生相應的變化。當然,應對這種情況,最好的方式是重新調整模組搜尋路徑,而不是修改程式碼中的完整名稱。

    模組搜尋路徑

    要取得關於模組搜尋路徑的資訊,你可以檢視Python 模組搜尋路徑介紹,模組搜尋路徑中的目錄有哪些一節。

    這裏,模組teacher和模組student位於同一目錄,student通過import陳述式匯入了teacher。開啟命令列執行student.py將是可行的(範例中命令列的目前目錄為student.py所在的資料夾,當然,你可以切換到其他位置),因為student.py所在的目錄會被新增至模組搜尋路徑,模組teacher的完整名稱是其自身。

    teacher.py
    print('teacher 模組!')
    student.py
    # 執行 student.py 可以正常匯入 teacher,因為 student.py 所在的目錄將被新增至搜尋路徑
    import teacher
    Windows
    python student.py
    teacher 模組!
    UNIX/Linux/macOS
    python3 student.py
    teacher 模組!

    調整模組student,為其匯入同一目錄的套件homework,在該套件對應的__init__.py檔案中,我們匯入了套件中的模組english。這裏請註意模組english的完整名稱homework.english,他基於student.py所在的位置。

    student.py
    # …
    # homework 套件也可以被正常匯入
    import homework
    homework/__init__.py
    print('homework 套件!')
    
    # 這裏的完整名稱基於 student.py 所在的目錄 import homework.english
    homework/english.py
    print('english 模組!')
    Windows
    python student.py
    teacher 模組!
    homework 套件!
    english 模組!
    UNIX/Linux/macOS
    python3 student.py
    teacher 模組!
    homework 套件!
    english 模組!

    對於完整名稱homework.english,如果我們直接執行homework套件的__init__.py檔案(範例中命令列的目前目錄為__init__.py所在的資料夾,當然,你可以切換到其他位置),那麽將產生一個錯誤。因為模組搜尋路徑已經不再包含student.py所在的目錄,完整名稱homework.english應改為english

    Windows
    python __init__.py
    homework 套件!

    ModuleNotFoundError: No module named 'homework'
    UNIX/Linux/macOS
    python3 __init__.py
    homework 套件!

    ModuleNotFoundError: No module named 'homework'

    Python 模組快取

    無論是哪種快取,使用他們的目的在於提高執行效率,以犧牲部分儲存空間為代價,避免大量重複和耗時的工作。Python 的模組快取包含了已經載入的模組或套件,他們儲存在sys模組的modules變數中,該變數是一個字典,字典中的鍵對應了模組的完整名稱,字典中的值對應了表示模組的ModuleType物件。

    ModuleType 物件

    你可以將ModuleType物件視為模組在程式碼層面的真實實作,一般情況下他們儲存在sys.modules字典中。開發人員可以編寫程式碼,來主動建立一個ModuleType物件並將其加入模組快取。

    sys.modules 中的 None 會導致無法匯入相關模組或套件

    如果將字典sys.modules中某個鍵值組的值設定為None,那麽嘗試匯入該鍵值組對應的模組會引發例外狀況ModuleNotFoundError。對於在設定None之前匯入的模組,則可以延續其有效性。

    匯入系統

    想要取得更多關於匯入系統的資訊,你可以檢視什麽是 Python 匯入系統一節。

    這裏模組car定義了類別Car,在腳本檔案cache_none.py中,我們提前將模組car對應的快取設定為None,然後使用import陳述式將其匯入,例外狀況ModuleNotFoundError會被擲回。

    car.py
    # 一個表示汽車的類別
    class Car:
    	pass
    cache_none.py
    import sys
    # 模組 car 的完整名稱為 car,這裏提前將其快取設定為 None
    sys.modules['car'] = None
    
    # 匯入模組 car 將導致例外狀況 import car
    ModuleNotFoundError: import of car halted; None in sys.modules

    清除 Python 模組快取

    雖然沒有必要,但你可以清空模組快取,這將導致下一次的匯入操作需要重新載入相關的模組或套件。

    重新匯入的模組與之前匯入的模組不同

    如果一個模組對應的快取被清除,那麽重新匯入的模組與之前匯入的模組,是兩個不同的ModuleType物件,模組中定義的類別也會有所區別。

    在下面的範例中,我們將模組car的快取儲存至變數module1,並建立Car的執行個體car1,之後清除模組的快取重新匯入,建立Car的執行個體car2,對比前後的模組快取和Car物件的型別,會發現他們並不相同。

    cache_clear.py
    import sys
    
    # 首次匯入模組 car,並建立 Car 物件 import car module1 = sys.modules['car'] car1 = car.Car()
    # 清除模組 car 的快取 del sys.modules['car']
    # 再次匯入模組 car,並建立 Car 物件 import car module2 = sys.modules['car'] car2 = car.Car()
    print(f'module1 == module2 能成立?{module1 == module2}') print(f'car1 與 car2 的型別相同?{type(car1) == type(car2)}')
    module1 == module2 能成立?False
    car1 與 car2 的型別相同?False

    原始碼

    teacher.py·codebeatme/python-reference·GitHub
    student.py·codebeatme/python-reference·GitHub
    homework/__init__.py·codebeatme/python-reference·GitHub
    homework/english.py·codebeatme/python-reference·GitHub
    car.py·codebeatme/python-reference·GitHub
    cache_none.py·codebeatme/python-reference·GitHub
    cache_clear.py·codebeatme/python-reference·GitHub