### 導航
- [索引](../genindex.xhtml "總目錄")
- [模塊](../py-modindex.xhtml "Python 模塊索引") |
- [下一頁](expressions.xhtml "6. 表達式") |
- [上一頁](executionmodel.xhtml "4. 執行模型") |
- 
- [Python](https://www.python.org/) ?
- zh\_CN 3.7.3 [文檔](../index.xhtml) ?
- [Python 語言參考](index.xhtml) ?
- $('.inline-search').show(0); |
# 5. 導入系統
一個 [module](../glossary.xhtml#term-module) 內的 Python 代碼通過 [importing](../glossary.xhtml#term-importing) 操作就能夠訪問另一個模塊內的代碼。 [`import`](simple_stmts.xhtml#import) 語句是發起調用導入機制的最常用方式,但不是唯一的方式。 [`importlib.import_module()`](../library/importlib.xhtml#importlib.import_module "importlib.import_module") 以及內置的 [`__import__()`](../library/functions.xhtml#__import__ "__import__") 等函數也可以被用來發起調用導入機制。
[`import`](simple_stmts.xhtml#import) 語句結合了兩個操作;它先搜索指定名稱的模塊,然后將搜索結果綁定到當前作用域中的名稱。 `import` 語句的搜索操作定義為對 [`__import__()`](../library/functions.xhtml#__import__ "__import__") 函數的調用并帶有適當的參數。 [`__import__()`](../library/functions.xhtml#__import__ "__import__") 的返回值會被用于執行 `import` 語句的名稱綁定操作。 請參閱 `import` 語句了解名稱綁定操作的更多細節。
對 [`__import__()`](../library/functions.xhtml#__import__ "__import__") 的直接調用將僅執行模塊搜索以及在找到時的模塊創建操作。 不過也可能產生某些副作用,例如導入父包和更新各種緩存 (包括 [`sys.modules`](../library/sys.xhtml#sys.modules "sys.modules")),只有 [`import`](simple_stmts.xhtml#import) 語句會執行名稱綁定操作。
當 [`import`](simple_stmts.xhtml#import) 語句被執行時,標準的內置 [`__import__()`](../library/functions.xhtml#__import__ "__import__") 函數會被調用。 其他發起調用導入系統的機制 (例如 [`importlib.import_module()`](../library/importlib.xhtml#importlib.import_module "importlib.import_module")) 可能會選擇繞過 [`__import__()`](../library/functions.xhtml#__import__ "__import__") 并使用它們自己的解決方案來實現導入機制。
當一個模塊首次被導入時,Python 會搜索該模塊,如果找到就創建一個 module 對象 [1](#fnmo) 并初始化它。 如果指定名稱的模塊未找到,則會引發 [`ModuleNotFoundError`](../library/exceptions.xhtml#ModuleNotFoundError "ModuleNotFoundError")。 當發起調用導入機制時,Python 會實現多種策略來搜索指定名稱的模塊。 這些策略可以通過使用使用下文所描述的多種鉤子來加以修改和擴展。
在 3.3 版更改: 導入系統已被更新以完全實現 [**PEP 302**](https://www.python.org/dev/peps/pep-0302) \[https://www.python.org/dev/peps/pep-0302\] 中的第二階段要求。 不會再有任何隱式的導入機制 —— 整個導入系統都通過 [`sys.meta_path`](../library/sys.xhtml#sys.meta_path "sys.meta_path") 暴露出來。 此外,對原生命名空間包的支持也已被實現 (參見 [**PEP 420**](https://www.python.org/dev/peps/pep-0420) \[https://www.python.org/dev/peps/pep-0420\])。
## 5.1. [`importlib`](../library/importlib.xhtml#module-importlib "importlib: The implementation of the import machinery.")
[`importlib`](../library/importlib.xhtml#module-importlib "importlib: The implementation of the import machinery.") 模塊提供了一個豐富的 API 用來與導入系統進行交互。 例如 [`importlib.import_module()`](../library/importlib.xhtml#importlib.import_module "importlib.import_module") 提供了相比內置的 [`__import__()`](../library/functions.xhtml#__import__ "__import__") 更推薦、更簡單的 API 用來發起調用導入機制。 更多細節請參看 [`importlib`](../library/importlib.xhtml#module-importlib "importlib: The implementation of the import machinery.") 庫文檔。
## 5.2. 包
Python 只有一種模塊對象類型,所有模塊都屬于該類型,無論模塊是用 Python、C 還是別的語言實現。 為了幫助組織模塊并提供名稱層次結構,Python 還引入了 [包](../glossary.xhtml#term-package) 的概念。
你可以把包看成是文件系統中的目錄,并把模塊看成是目錄中的文件,但請不要對這個類似做過于字面的理解,因為包和模塊不是必須來自于文件系統。 為了方便理解本文檔,我們將繼續使用這種目錄和文件的類比。 與文件系統一樣,包通過層次結構進行組織,在包之內除了一般的模塊,還可以有子包。
要注意的一個重點概念是所有包都是模塊,但并非所有模塊都是包。 或者換句話說,包只是一種特殊的模塊。 特別地,任何具有 `__path__` 屬性的模塊都會被當作是包。
所有模塊都有自己的名字。 子包名與其父包名以點號分隔,與 Python 的標準屬性訪問語法一致。 例如你可能看到一個名為 [`sys`](../library/sys.xhtml#module-sys "sys: Access system-specific parameters and functions.") 的模塊,以及一個名為 [`email`](../library/email.xhtml#module-email "email: Package supporting the parsing, manipulating, and generating email messages.") 的包,這個包又有一個名為 [`email.mime`](../library/email.mime.xhtml#module-email.mime "email.mime: Build MIME messages.") 的子包和該子包中的名為 `email.mime.text` 的子包。
### 5.2.1. 正規包
Python 定義了兩種類型的包,[正規包](../glossary.xhtml#term-regular-package) 和 [命名空間包](../glossary.xhtml#term-namespace-package)。 正規包是傳統的包類型,它們在 Python 3.2 及之前就已存在。 正規包通常以一個包含 `__init__.py` 文件的目錄形式實現。 當一個正規包被導入時,這個 `__init__.py` 文件會隱式地被執行,它所定義的對象會被綁定到該包命名空間中的名稱。`__init__.py` 文件可以包含與任何其他模塊中所包含的 Python 代碼相似的代碼,Python 將在模塊被導入時為其添加額外的屬性。
例如,以下文件系統布局定義了一個最高層級的 `parent` 包和三個子包:
```
parent/
__init__.py
one/
__init__.py
two/
__init__.py
three/
__init__.py
```
導入 `parent.one` 將隱式地執行 `parent/__init__.py` 和 `parent/one/__init__.py`。 后續導入 `parent.two` 或 `parent.three` 則將分別執行 `parent/two/__init__.py` 和 `parent/three/__init__.py`。
### 5.2.2. 命名空間包
命名空間包是由多個 [部分](../glossary.xhtml#term-portion) 構成的,每個部分為父包增加一個子包。 各個部分可能處于文件系統的不同位置。 部分也可能處于 zip 文件中、網絡上,或者 Python 在導入期間可以搜索的其他地方。 命名空間包并不一定會直接對應到文件系統中的對象;它們有可能是無實體表示的虛擬模塊。
命名空間包的 `__path__` 屬性不使用普通的列表。 而是使用定制的可迭代類型,如果其父包的路徑 (或者最高層級包的 [`sys.path`](../library/sys.xhtml#sys.path "sys.path")) 發生改變,這種對象會在該包內的下一次導入嘗試時自動執行新的對包部分的搜索。
命名空間包沒有 `parent/__init__.py` 文件。 實際上,在導入搜索期間可能找到多個 `parent` 目錄,每個都由不同的部分所提供。 因此 `parent/one` 的物理位置不一定與 `parent/two` 相鄰。 在這種情況下,Python 將為頂級的 `parent` 包創建一個命名空間包,無論是它本身還是它的某個子包被導入。
另請參閱 [**PEP 420**](https://www.python.org/dev/peps/pep-0420) \[https://www.python.org/dev/peps/pep-0420\] 了解對命名空間包的規格描述。
## 5.3. 搜索
為了開始搜索,Python 需要被導入模塊(或者包,對于當前討論來說兩者沒有差別)的完整 [限定名稱](../glossary.xhtml#term-qualified-name)。 此名稱可以來自 [`import`](simple_stmts.xhtml#import) 語句所帶的各種參數,或者來自傳給 [`importlib.import_module()`](../library/importlib.xhtml#importlib.import_module "importlib.import_module") 或 [`__import__()`](../library/functions.xhtml#__import__ "__import__") 函數的形參。
此名稱會在導入搜索的各個階段被使用,它也可以是指向一個子模塊的帶點號路徑,例如 `foo.bar.baz`。 在這種情況下,Python 會先嘗試導入 `foo`,然后是 `foo.bar`,最后是 `foo.bar.baz`。 如果這些導入中的任何一個失敗,都會引發 [`ModuleNotFoundError`](../library/exceptions.xhtml#ModuleNotFoundError "ModuleNotFoundError")。
### 5.3.1. 模塊緩存
在導入搜索期間首先會被檢查的地方是 [`sys.modules`](../library/sys.xhtml#sys.modules "sys.modules")。 這個映射起到緩存之前導入的所有模塊的作用(包括其中間路徑)。 因此如果之前導入過 `foo.bar.baz`,則 [`sys.modules`](../library/sys.xhtml#sys.modules "sys.modules") 將包含 `foo`, `foo.bar` 和 `foo.bar.baz` 條目。 每個鍵的值就是相應的模塊對象。
在導入期間,會在 [`sys.modules`](../library/sys.xhtml#sys.modules "sys.modules") 查找模塊名稱,如存在則其關聯的值就是需要導入的模塊,導入過程完成。 然而,如果值為 `None`,則會引發 [`ModuleNotFoundError`](../library/exceptions.xhtml#ModuleNotFoundError "ModuleNotFoundError")。 如果找不到指定模塊名稱,Python 將繼續搜索該模塊。
[`sys.modules`](../library/sys.xhtml#sys.modules "sys.modules") 是可寫的。刪除鍵可能不會破壞關聯的模塊(因為其他模塊可能會保留對它的引用),但它會使命名模塊的緩存條目無效,導致 Python 在下次導入時重新搜索命名模塊。鍵也可以賦值為 `None` ,強制下一次導入模塊導致 [`ModuleNotFoundError`](../library/exceptions.xhtml#ModuleNotFoundError "ModuleNotFoundError") 。
但是要小心,因為如果你還保有對某個模塊對象的引用,同時停用其在 [`sys.modules`](../library/sys.xhtml#sys.modules "sys.modules") 中的緩存條目,然后又再次導入該名稱的模塊,則前后兩個模塊對象將 *不是* 同一個。 相反地,[`importlib.reload()`](../library/importlib.xhtml#importlib.reload "importlib.reload") 將重用 *同一個* 模塊對象,并簡單地通過重新運行模塊的代碼來重新初始化模塊內容。
### 5.3.2. 查找器和加載器
如果指定名稱的模塊在 [`sys.modules`](../library/sys.xhtml#sys.modules "sys.modules") 找不到,則將發起調用 Python 的導入協議以查找和加載該模塊。 此協議由兩個概念性模塊構成,即 [查找器](../glossary.xhtml#term-finder) 和 [加載器](../glossary.xhtml#term-loader)。 查找器的任務是確定是否能使用其所知的策略找到該名稱的模塊。 同時實現這兩種接口的對象稱為 [導入器](../glossary.xhtml#term-importer) —— 它們在確定能加載所需的模塊時會返回其自身。
Python 包含了多個默認查找器和導入器。 第一個知道如何定位內置模塊,第二個知道如何定位凍結模塊。 第三個默認查找器會在 [import path](../glossary.xhtml#term-import-path) 中搜索模塊。 [import path](../glossary.xhtml#term-import-path) 是一個由文件系統路徑或 zip 文件組成的位置列表。 它還可以擴展為搜索任意可定位資源,例如由 URL 指定的資源。
導入機制是可擴展的,因此可以加入新的查找器以擴展模塊搜索的范圍和作用域。
查找器并不真正加載模塊。 如果它們能找到指定名稱的模塊,會返回一個 *模塊規格說明*,這是對模塊導入相關信息的封裝,供后續導入機制用于在加載模塊時使用。
以下各節描述了有關查找器和加載器協議的更多細節,包括你應該如何創建并注冊新的此類對象來擴展導入機制。
在 3.4 版更改: 在之前的 Python 版本中,查找器會直接返回 [加載器](../glossary.xhtml#term-loader),現在它們則返回模塊規格說明,其中 *包含* 加載器。 加載器仍然在導入期間被使用,但負擔的任務有所減少。
### 5.3.3. 導入鉤子
導入機制被設計為可擴展;其中的基本機制是 *導入鉤子*。 導入鉤子有兩種類型: *元鉤子* 和 *導入路徑鉤子*。
元鉤子在導入過程開始時被調用,此時任何其他導入過程尚未發生,但 [`sys.modules`](../library/sys.xhtml#sys.modules "sys.modules") 緩存查找除外。 這允許元鉤子重載 [`sys.path`](../library/sys.xhtml#sys.path "sys.path") 過程、凍結模塊甚至內置模塊。 元鉤子的注冊是通過向 [`sys.meta_path`](../library/sys.xhtml#sys.meta_path "sys.meta_path") 添加新的查找器對象,具體如下所述。
導入路徑鉤子是作為 [`sys.path`](../library/sys.xhtml#sys.path "sys.path") (或 `package.__path__`) 過程的一部分,在遇到它們所關聯的路徑項的時候被調用。 導入路徑鉤子的注冊是通過向 [`sys.path_hooks`](../library/sys.xhtml#sys.path_hooks "sys.path_hooks") 添加新的可調用對象,具體如下所述。
### 5.3.4. 元路徑
當指定名稱的模塊在 [`sys.modules`](../library/sys.xhtml#sys.modules "sys.modules") 中找不到時,Python 會接著搜索 [`sys.meta_path`](../library/sys.xhtml#sys.meta_path "sys.meta_path"),其中包含元路徑查找器對象列表。 這些查找器按順序被查詢以確定它們是否知道如何處理該名稱的模塊。 元路徑查找器必須實現名為 [`find_spec()`](../library/importlib.xhtml#importlib.abc.MetaPathFinder.find_spec "importlib.abc.MetaPathFinder.find_spec") 的方法,該方法接受三個參數:名稱、導入路徑和目標模塊(可選)。 元路徑查找器可使用任何策略來確定它是否能處理指定名稱的模塊。
如果元路徑查找器知道如何處理指定名稱的模塊,它將返回一個說明對象。 如果它不能處理該名稱的模塊,則會返回 `None`。 如果 [`sys.meta_path`](../library/sys.xhtml#sys.meta_path "sys.meta_path") 處理過程到達列表末尾仍未返回說明對象,則將引發 [`ModuleNotFoundError`](../library/exceptions.xhtml#ModuleNotFoundError "ModuleNotFoundError")。 任何其他被引發異常將直接向上傳播,并放棄導入過程。
元路徑查找器的 [`find_spec()`](../library/importlib.xhtml#importlib.abc.MetaPathFinder.find_spec "importlib.abc.MetaPathFinder.find_spec") 方法調用帶有兩到三個參數。 第一個是被導入模塊的完整限定名稱,例如 `foo.bar.baz`。 第二個參數是供模塊搜索使用的路徑條目。 對于最高層級模塊,第二個參數為 `None`,但對于子模塊或子包,第二個參數為父包 `__path__` 屬性的值。 如果相應的 `__path__` 屬性無法訪問,將引發 [`ModuleNotFoundError`](../library/exceptions.xhtml#ModuleNotFoundError "ModuleNotFoundError")。 第三個參數是一個將被作為稍后加載目標的現有模塊對象。 導入系統僅會在重加載期間傳入一個目標模塊。
對于單個導入請求可以多次遍歷元路徑。 例如,假設所涉及的模塊都尚未被緩存,則導入 `foo.bar.baz` 將首先執行頂級的導入,在每個元路徑查找器 (`mpf`) 上調用 `mpf.find_spec("foo", None, None)`。 在導入 `foo` 之后,`foo.bar` 將通過第二次遍歷元路徑來導入,調用 `mpf.find_spec("foo.bar", foo.__path__, None)`。 一旦 `foo.bar` 完成導入,最后一次遍歷將調用 `mpf.find_spec("foo.bar.baz", foo.bar.__path__, None)`。
有些元路徑查找器只支持頂級導入。 當把 `None` 以外的對象作為第三個參數傳入時,這些導入器將總是返回 `None`。
Python 的默認 [`sys.meta_path`](../library/sys.xhtml#sys.meta_path "sys.meta_path") 具有三種元路徑查找器,一種知道如何導入內置模塊,一種知道如何導入凍結模塊,還有一種知道如何導入來自 [import path](../glossary.xhtml#term-import-path) 的模塊 (即 [path based finder](../glossary.xhtml#term-path-based-finder))。
在 3.4 版更改: 元路徑查找器的 [`find_spec()`](../library/importlib.xhtml#importlib.abc.MetaPathFinder.find_spec "importlib.abc.MetaPathFinder.find_spec") 方法替代了 [`find_module()`](../library/importlib.xhtml#importlib.abc.MetaPathFinder.find_module "importlib.abc.MetaPathFinder.find_module"),后者現已棄用,它將繼續可用但不會再做改變,導入機制僅會在查找器未實現 `find_spec()` 時嘗試使用它。
## 5.4. 加載
當一個模塊說明被找到時,導入機制將在加載該模塊時使用它(及其所包含的加載器)。 下面是導入的加載部分所發生過程的簡要說明:
```
module = None
if spec.loader is not None and hasattr(spec.loader, 'create_module'):
# It is assumed 'exec_module' will also be defined on the loader.
module = spec.loader.create_module(spec)
if module is None:
module = ModuleType(spec.name)
# The import-related module attributes get set here:
_init_module_attrs(spec, module)
if spec.loader is None:
if spec.submodule_search_locations is not None:
# namespace package
sys.modules[spec.name] = module
else:
# unsupported
raise ImportError
elif not hasattr(spec.loader, 'exec_module'):
module = spec.loader.load_module(spec.name)
# Set __loader__ and __package__ if missing.
else:
sys.modules[spec.name] = module
try:
spec.loader.exec_module(module)
except BaseException:
try:
del sys.modules[spec.name]
except KeyError:
pass
raise
return sys.modules[spec.name]
```
請注意以下細節:
> - 如果在 [`sys.modules`](../library/sys.xhtml#sys.modules "sys.modules") 中存在指定名稱的模塊對象,導入操作會已經將其返回。
> - 在加載器執行模塊代碼之前,該模塊將存在于 [`sys.modules`](../library/sys.xhtml#sys.modules "sys.modules") 中。 這一點很關鍵,因為該模塊代碼可能(直接或間接地)導入其自身;預先將其添加到 [`sys.modules`](../library/sys.xhtml#sys.modules "sys.modules") 可防止在最壞情況下的無限遞歸和最好情況下的多次加載。
> - 如果加載失敗,則該模塊 -- 只限加載失敗的模塊 -- 將從 [`sys.modules`](../library/sys.xhtml#sys.modules "sys.modules") 中移除。 任何已存在于 [`sys.modules`](../library/sys.xhtml#sys.modules "sys.modules") 緩存的模塊,以及任何作為附帶影響被成功加載的模塊仍會保留在緩存中。 這與重新加載不同,后者會把即使加載失敗的模塊也保留在 [`sys.modules`](../library/sys.xhtml#sys.modules "sys.modules") 中。
> - 在模塊創建完成但還未執行之前,導入機制會設置導入相關模塊屬性(在上面的示例偽代碼中為 “\_init\_module\_attrs”),詳情參見 [后續部分](#import-mod-attrs)。
> - 模塊執行是加載的關鍵時刻,在此期間將填充模塊的命名空間。 執行會完全委托給加載器,由加載器決定要填充的內容和方式。
> - 在加載過程中創建并傳遞給 exec\_module() 的模塊并不一定就是在導入結束時返回的模塊 [2](#fnlo)。
在 3.4 版更改: 導入系統已經接管了加載器建立樣板的責任。 這些在以前是由 [`importlib.abc.Loader.load_module()`](../library/importlib.xhtml#importlib.abc.Loader.load_module "importlib.abc.Loader.load_module") 方法來執行的。
### 5.4.1. 加載器
模塊加載器提供關鍵的加載功能:模塊執行。 導入機制調用 [`importlib.abc.Loader.exec_module()`](../library/importlib.xhtml#importlib.abc.Loader.exec_module "importlib.abc.Loader.exec_module") 方法并傳入一個參數來執行模塊對象。 從 [`exec_module()`](../library/importlib.xhtml#importlib.abc.Loader.exec_module "importlib.abc.Loader.exec_module") 返回的任何值都將被忽略。
加載器必須滿足下列要求:
> - 如果模塊是一個 Python 模塊(而非內置模塊或動態加載的擴展),加載器應該在模塊的全局命名空間 (`module.__dict__`) 中執行模塊的代碼。
> - 如果加載器無法執行指定模塊,它應該引發 [`ImportError`](../library/exceptions.xhtml#ImportError "ImportError"),不過在 [`exec_module()`](../library/importlib.xhtml#importlib.abc.Loader.exec_module "importlib.abc.Loader.exec_module") 期間引發的任何其他異常也會被傳播。
在許多情況下,查找器和加載器可以是同一對象;在此情況下 [`find_spec()`](../library/importlib.xhtml#importlib.abc.MetaPathFinder.find_spec "importlib.abc.MetaPathFinder.find_spec") 方法將返回一個規格說明,其中加載器會被設為 `self`。
模塊加載器可以選擇通過實現 [`create_module()`](../library/importlib.xhtml#importlib.abc.Loader.create_module "importlib.abc.Loader.create_module") 方法在加載期間創建模塊對象。 它接受一個參數,即模塊規格說明,并返回新的模塊對象供加載期間使用。 `create_module()` 不需要在模塊對象上設置任何屬性。 如果模塊返回 `None`,導入機制將自行創建新模塊。
3\.4 新版功能: 加載器的 [`create_module()`](../library/importlib.xhtml#importlib.abc.Loader.create_module "importlib.abc.Loader.create_module") 方法。
在 3.4 版更改: [`load_module()`](../library/importlib.xhtml#importlib.abc.Loader.load_module "importlib.abc.Loader.load_module") 方法被 [`exec_module()`](../library/importlib.xhtml#importlib.abc.Loader.exec_module "importlib.abc.Loader.exec_module") 所替代,導入機制會對加載的所有樣板責任作出假定。
為了與現有的加載器兼容,導入機制會使用導入器的 `load_module()` 方法,如果它存在且導入器也未實現 `exec_module()`。 但是,`load_module()` 現已棄用,加載器應該轉而實現 `exec_module()`。
除了執行模塊之外,`load_module()` 方法必須實現上文描述的所有樣板加載功能。 所有相同的限制仍然適用,并帶有一些附加規定:
> - 如果 [`sys.modules`](../library/sys.xhtml#sys.modules "sys.modules") 中存在指定名稱的模塊對象,加載器必須使用已存在的模塊。 (否則 [`importlib.reload()`](../library/importlib.xhtml#importlib.reload "importlib.reload") 將無法正確工作。) 如果該名稱模塊不存在于 [`sys.modules`](../library/sys.xhtml#sys.modules "sys.modules") 中,加載器必須創建一個新的模塊對象并將其加入 [`sys.modules`](../library/sys.xhtml#sys.modules "sys.modules")。
> - 在加載器執行模塊代碼之前,模塊 *必須* 存在于 [`sys.modules`](../library/sys.xhtml#sys.modules "sys.modules") 之中,以防止無限遞歸或多次加載。
> - 如果加載失敗,加載器必須移除任何它已加入到 [`sys.modules`](../library/sys.xhtml#sys.modules "sys.modules") 中的模塊,但它必須 **僅限** 移除加載失敗的模塊,且所移除的模塊應為加載器自身顯式加載的。
在 3.5 版更改: 當 `exec_module()` 已定義但 `create_module()` 未定義時將引發 [`DeprecationWarning`](../library/exceptions.xhtml#DeprecationWarning "DeprecationWarning")。
在 3.6 版更改: 當 `exec_module()` 已定義但 `create_module()` 未定義時將引發 [`ImportError`](../library/exceptions.xhtml#ImportError "ImportError")。
### 5.4.2. 子模塊
當使用任意機制 (例如 `importlib` API, `import` 及 `import-from` 語句或者內置的 `__import__()`) 加載一個子模塊時,父模塊的命名空間中會添加一個對子模塊對象的綁定。 例如,如果包 `spam` 有一個子模塊 `foo`,則在導入 `spam.foo` 之后,`spam` 將具有一個 綁定到相應子模塊的 `foo` 屬性。 假如現在有如下的目錄結構:
```
spam/
__init__.py
foo.py
bar.py
```
并且 `spam/__init__.py` 中有如下幾行內容:
```
from .foo import Foo
from .bar import Bar
```
則執行如下代碼將在 `spam` 模塊中添加對 `foo` 和 `bar` 的名稱綁定:
```
>>> import spam
>>> spam.foo
<module 'spam.foo' from '/tmp/imports/spam/foo.py'>
>>> spam.bar
<module 'spam.bar' from '/tmp/imports/spam/bar.py'>
```
按照通常的 Python 名稱綁定規則,這看起來可能會令人驚訝,但它實際上是導入系統的一個基本特性。 保持不變的一點是如果你有 `sys.modules['spam']` 和 `sys.modules['spam.foo']` (例如在上述導入之后就是如此),則后者必須顯示為前者的 `foo` 屬性。
### 5.4.3. 模塊規格說明
導入機制在導入期間會使用有關每個模塊的多種信息,特別是加載之前。 大多數信息都是所有模塊通用的。 模塊規格說明的目的是基于每個模塊來封裝這些導入相關信息。
在導入期間使用規格說明可允許狀態在導入系統各組件之間傳遞,例如在創建模塊規格說明的查找器和執行模塊的加載器之間。 最重要的一點是,它允許導入機制執行加載的樣板操作,在沒有模塊規格說明的情況下這是加載器的責任。
模塊的規格說明會作為模塊對象的 `__spec__` 屬性對外公開。 有關模塊規格的詳細內容請參閱 [`ModuleSpec`](../library/importlib.xhtml#importlib.machinery.ModuleSpec "importlib.machinery.ModuleSpec")。
3\.4 新版功能.
### 5.4.4. 導入相關的模塊屬性
導入機制會在加載期間會根據模塊的規格說明填充每個模塊對象的這些屬性,并在加載器執行模塊之前完成。
`__name__``__name__` 屬性必須被設為模塊的完整限定名稱。 此名稱被用來在導入系統中唯一地標識模塊。
`__loader__``__loader__` 屬性必須被設為導入系統在加載模塊時使用的加載器對象。 這主要是用于內省,但也可用于額外的加載器專用功能,例如獲取關聯到加載器的數據。
`__package__`模塊的 `__package__` 屬性必須設定。 其取值必須為一個字符串,但可以與 `__name__` 取相同的值。 當模塊是包時,其 `__package__` 值應該設為其 `__name__` 值。 當模塊不是包時,對于最高層級模塊 `__package__` 應該設為空字符串,對于子模塊則應該設為其父包名。 更多詳情可參閱 [**PEP 366**](https://www.python.org/dev/peps/pep-0366) \[https://www.python.org/dev/peps/pep-0366\]。
該屬性取代 `__name__` 被用來為主模塊計算顯式相對導入,相關定義見 [**PEP 366**](https://www.python.org/dev/peps/pep-0366) \[https://www.python.org/dev/peps/pep-0366\]。 預期它與 `__spec__.parent` 具有相同的值。
在 3.6 版更改: `__package__` 預期與 `__spec__.parent` 具有相同的值。
`__spec__``__spec__` 屬性必須設為在導入模塊時要使用的模塊規格說明。 對 `__spec__` 的正確設定將同時作用于 [解釋器啟動期間初始化的模塊](toplevel_components.xhtml#programs)。 唯一的例外是 `__main__`,其中的 `__spec__` 會 [在某些情況下設為 None](#main-spec).
當 `__package__` 未定義時, `__spec__.parent` 會被用作回退項。
3\.4 新版功能.
在 3.6 版更改: 當 `__package__` 未定義時,`__spec__.parent` 會被用作回退項。
`__path__`如果模塊為包(不論是正規包還是命名空間包),則必須設置模塊對象的 `__path__` 屬性。 屬性值必須為可迭代對象,但如果 `__path__` 沒有進一步的用處則可以為空。 如果 `__path__` 不為空,則在迭代時它應該產生字符串。 有關 `__path__` 語義的更多細節將在 [下文](#package-path-rules) 中給出。
不是包的模塊不應該具有 `__path__` 屬性。
`__file__``__cached__``__file__` 是可選項。 如果設置,此屬性的值必須為字符串。 導入系統可以選擇在其沒有語法意義時不設置 `__file__` (例如從數據庫加載的模塊)。
如果設置了 `__file__`,則也可以再設置 `__cached__` 屬性,后者取值為編譯版本代碼(例如字節碼文件)所在的路徑。 設置此屬性不要求文件已存在;該路徑可以簡單地指向應該存放編譯文件的位置 (參見 [**PEP 3147**](https://www.python.org/dev/peps/pep-3147) \[https://www.python.org/dev/peps/pep-3147\])。
當未設置 `__file__` 時也可以設置 `__cached__`。 但是,那樣的場景很不典型。 最終,加載器會使用 `__file__` 和/或 `__cached__`。 因此如果一個加載器可以從緩存加載模塊但是不能從文件加載,那種非典型場景就是適當的。
### 5.4.5. module.\_\_path\_\_
根據定義,如果一個模塊具有 `__path__` 屬性,它就是包。
包的 `__path__` 屬性會在導入其子包期間被使用。 在導入機制內部,它的功能與 [`sys.path`](../library/sys.xhtml#sys.path "sys.path") 基本相同,即在導入期間提供一個模塊搜索位置列表。 但是,`__path__` 通常會比 [`sys.path`](../library/sys.xhtml#sys.path "sys.path") 受到更多限制。
`__path__` 必須是由字符串組成的可迭代對象,但它也可以為空。 作用于 [`sys.path`](../library/sys.xhtml#sys.path "sys.path") 的規則同樣適用于包的 `__path__`,并且 [`sys.path_hooks`](../library/sys.xhtml#sys.path_hooks "sys.path_hooks") (見下文) 會在遍歷包的 `__path__` 時被查詢。
包的 `__init__.py` 文件可以設置或更改包的 `__path__` 屬性,而且這是在 [**PEP 420**](https://www.python.org/dev/peps/pep-0420) \[https://www.python.org/dev/peps/pep-0420\] 之前實現命名空間包的典型方式。 隨著 [**PEP 420**](https://www.python.org/dev/peps/pep-0420) \[https://www.python.org/dev/peps/pep-0420\] 的引入,命名空間包不再需要提供僅包含 `__path__` 操控代碼的 `__init__.py` 文件;導入機制會自動為命名空間包正確地設置 `__path__`。
### 5.4.6. 模塊的 repr
默認情況下,全部模塊都具有一個可用的 repr,但是你可以依據上述的屬性設置,在模塊的規格說明中更為顯式地控制模塊對象的 repr。
如果模塊具有 spec (`__spec__`),導入機制將嘗試用它來生成一個 repr。 如果生成失敗或找不到 spec,導入系統將使用模塊中的各種可用信息來制作一個默認 repr。 它將嘗試使用 `module.__name__`, `module.__file__` 以及 `module.__loader__` 作為 repr 的輸入,并將任何丟失的信息賦為默認值。
以下是所使用的確切規則:
> - 如果模塊具有 `__spec__` 屬性,其中的規格信息會被用來生成 repr。 被查詢的屬性有 "name", "loader", "origin" 和 "has\_location" 等等。
> - 如果模塊具有 `__file__` 屬性,這會被用作模塊 repr 的一部分。
> - 如果模塊沒有 `__file__` 但是有 `__loader__` 且取值不為 `None`,則加載器的 repr 會被用作模塊 repr 的一部分。
> - 對于其他情況,僅在 repr 中使用模塊的 `__name__`。
在 3.4 版更改: [`loader.module_repr()`](../library/importlib.xhtml#importlib.abc.Loader.module_repr "importlib.abc.Loader.module_repr") 已棄用,導入機制現在使用模塊規格說明來生成模塊 repr。
為了向后兼容 Python 3.3,如果加載器定義了 [`module_repr()`](../library/importlib.xhtml#importlib.abc.Loader.module_repr "importlib.abc.Loader.module_repr") 方法,則會在嘗試上述兩種方式之前先調用該方法來生成模塊 repr。 但請注意此方法已棄用。
### 5.4.7. 已緩存字節碼的失效
在 Python 從 `.pyc` 文件加載已緩存字節碼之前,它會檢查緩存是否由最新的 `.py` 源文件生成。 默認情況下,Python 通過在所寫入緩存文件中保存源文件的最近修改時間戳和大小來實現這一點。 在運行時,導入系統會通過比對緩存文件中保存的元數據和源文件的元數據確定該緩存的有效性。
Python 也支持“基于哈希的”緩存文件,即保存源文件內容的哈希值而不是其元數據。 存在兩種基于哈希的 `.pyc` 文件:檢查型和非檢查型。 對于檢查型基于哈希的 `.pyc` 文件,Python 會通過求哈希源文件并將結果哈希值與緩存文件中的哈希值比對來確定緩存有效性。 如果檢查型基于哈希的緩存文件被確定為失效,Python 會重新生成并寫入一個新的檢查型基于哈希的緩存文件。 對于非檢查型 `.pyc` 文件,只要其存在 Python 就會直接認定緩存文件有效。 確定基于哈希的 `.pyc` 文件有效性的行為可通過 [`--check-hash-based-pycs`](../using/cmdline.xhtml#cmdoption-check-hash-based-pycs) 旗標來重載。
在 3.7 版更改: 增加了基于哈希的 `.pyc` 文件。在此之前,Python 只支持基于時間戳來確定字節碼緩存的有效性。
## 5.5. 基于路徑的查找器
在之前已經提及,Python 帶有幾種默認的元路徑查找器。 其中之一是 [path based finder](../glossary.xhtml#term-path-based-finder) ([`PathFinder`](../library/importlib.xhtml#importlib.machinery.PathFinder "importlib.machinery.PathFinder")),它會搜索包含一個 [路徑條目](../glossary.xhtml#term-path-entry) 列表的 [import path](../glossary.xhtml#term-import-path)。 每個路徑條目指定一個用于搜索模塊的位置。
基于路徑的查找器自身并不知道如何進行導入。 它只是遍歷單獨的路徑條目,將它們各自關聯到某個知道如何處理特定類型路徑的路徑條目查找器。
默認的路徑條目查找器集合實現了在文件系統中查找模塊的所有語義,可處理多種特殊文件類型例如 Python 源碼 (`.py` 文件),Python 字節碼 (`.pyc` 文件) 以及共享庫 (例如 `.so` 文件)。 在標準庫中 [`zipimport`](../library/zipimport.xhtml#module-zipimport "zipimport: support for importing Python modules from ZIP archives.") 模塊的支持下,默認路徑條目查找器還能處理所有來自 zip 文件的上述文件類型。
路徑條目不必僅限于文件系統位置。 它們可以指向 URL、數據庫查詢或可以用字符串指定的任何其他位置。
基于路徑的查找器還提供了額外的鉤子和協議以便能擴展和定制可搜索路徑條目的類型。 例如,如果你想要支持網絡 URL 形式的路徑條目,你可以編寫一個實現 HTTP 語義在網絡上查找模塊的鉤子。 這個鉤子(可調用對象)應當返回一個支持下述協議的 [path entry finder](../glossary.xhtml#term-path-entry-finder),以被用來獲取一個專門針對來自網絡的模塊的加載器。
預先的警告:本節和上節都使用了 *查找器* 這一術語,并通過 [meta path finder](../glossary.xhtml#term-meta-path-finder) 和 [path entry finder](../glossary.xhtml#term-path-entry-finder) 兩個術語來明確區分它們。 這兩種類型的查找器非常相似,支持相似的協議,且在導入過程中以相似的方式運作,但關鍵的一點是要記住它們是有微妙差異的。 特別地,元路徑查找器作用于導入過程的開始,主要是啟動 [`sys.meta_path`](../library/sys.xhtml#sys.meta_path "sys.meta_path") 遍歷。
相比之下,路徑條目查找器在某種意義上說是基于路徑的查找器的實現細節,實際上,如果需要從 [`sys.meta_path`](../library/sys.xhtml#sys.meta_path "sys.meta_path") 移除基于路徑的查找器,并不會有任何路徑條目查找器被發起調用。
### 5.5.1. 路徑條目查找器
[path based finder](../glossary.xhtml#term-path-based-finder) 會負責查找和加載通過 [path entry](../glossary.xhtml#term-path-entry) 字符串來指定位置的 Python 模塊和包。 多數路徑條目所指定的是文件系統中的位置,但它們并不必受限于此。
作為一種元路徑查找器,[path based finder](../glossary.xhtml#term-path-based-finder) 實現了上文描述的 [`find_spec()`](../library/importlib.xhtml#importlib.abc.MetaPathFinder.find_spec "importlib.abc.MetaPathFinder.find_spec") 協議,但是它還對外公開了一些附加鉤子,可被用來定制模塊如何從 [import path](../glossary.xhtml#term-import-path) 查找和加載。
有三個變量由 [path based finder](../glossary.xhtml#term-path-based-finder), [`sys.path`](../library/sys.xhtml#sys.path "sys.path"), [`sys.path_hooks`](../library/sys.xhtml#sys.path_hooks "sys.path_hooks") 和 [`sys.path_importer_cache`](../library/sys.xhtml#sys.path_importer_cache "sys.path_importer_cache") 所使用。 包對象的 `__path__` 屬性也會被使用。 它們提供了可用于定制導入機制的額外方式。
[`sys.path`](../library/sys.xhtml#sys.path "sys.path") 包含一個提供模塊和包搜索位置的字符串列表。 它初始化自 `PYTHONPATH` 環境變量以及多種其他特定安裝和實現的默認設置。 [`sys.path`](../library/sys.xhtml#sys.path "sys.path") 條目可指定的名稱有文件系統中的目錄、zip 文件和其他可用于搜索模塊的潛在“位置”(參見 [`site`](../library/site.xhtml#module-site "site: Module responsible for site-specific configuration.") 模塊),例如 URL 或數據庫查詢等。 在 [`sys.path`](../library/sys.xhtml#sys.path "sys.path") 中只能出現字符串和字節串;所有其他數據類型都會被忽略。 字節串條目使用的編碼由單獨的 [路徑條目查找器](../glossary.xhtml#term-path-entry-finder) 來確定。
[path based finder](../glossary.xhtml#term-path-based-finder) 是一種 [meta path finder](../glossary.xhtml#term-meta-path-finder),因此導入機制會通過調用上文描述的基于路徑的查找器的 [`find_spec()`](../library/importlib.xhtml#importlib.machinery.PathFinder.find_spec "importlib.machinery.PathFinder.find_spec") 方法來啟動 [import path](../glossary.xhtml#term-import-path) 搜索。 當要向 [`find_spec()`](../library/importlib.xhtml#importlib.machinery.PathFinder.find_spec "importlib.machinery.PathFinder.find_spec") 傳入 `path` 參數時,它將是一個可遍歷的字符串列表 —— 通常為用來在其內部進行導入的包的 `__path__` 屬性。 如果 `path` 參數為 `None`,這表示最高層級的導入,將會使用 [`sys.path`](../library/sys.xhtml#sys.path "sys.path")。
基于路徑的查找器會迭代搜索路徑中的每個條目,并且每次都查找與路徑條目對應的 [path entry finder](../glossary.xhtml#term-path-entry-finder) ([`PathEntryFinder`](../library/importlib.xhtml#importlib.abc.PathEntryFinder "importlib.abc.PathEntryFinder"))。 因為這種操作可能很耗費資源(例如搜索會有 stat() 調用的開銷),基于路徑的查找器會維持一個緩存來將路徑條目映射到路徑條目查找器。 這個緩存放于 [`sys.path_importer_cache`](../library/sys.xhtml#sys.path_importer_cache "sys.path_importer_cache") (盡管如此命名,但這個緩存實際存放的是查找器對象而非僅限于 [importer](../glossary.xhtml#term-importer) 對象)。 通過這種方式,對特定 [path entry](../glossary.xhtml#term-path-entry) 位置的 [path entry finder](../glossary.xhtml#term-path-entry-finder) 的高耗費搜索只需進行一次。 用戶代碼可以自由地從 [`sys.path_importer_cache`](../library/sys.xhtml#sys.path_importer_cache "sys.path_importer_cache") 移除緩存條目,以強制基于路徑的查找器再次執行路徑條目搜索 [3](#fnpic)。
如果路徑條目不存在于緩存中,基于路徑的查找器會迭代 [`sys.path_hooks`](../library/sys.xhtml#sys.path_hooks "sys.path_hooks") 中的每個可調用對象。 對此列表中的每個 [路徑條目鉤子](../glossary.xhtml#term-path-entry-hook) 的調用會帶有一個參數,即要搜索的路徑條目。 每個可調用對象或是返回可處理路徑條目的 [path entry finder](../glossary.xhtml#term-path-entry-finder),或是引發 [`ImportError`](../library/exceptions.xhtml#ImportError "ImportError")。 基于路徑的查找器使用 [`ImportError`](../library/exceptions.xhtml#ImportError "ImportError") 來表示鉤子無法找到與 [path entry](../glossary.xhtml#term-path-entry) 相對應的 [path entry finder](../glossary.xhtml#term-path-entry-finder)。 該異常會被忽略并繼續進行 [import path](../glossary.xhtml#term-import-path) 的迭代。 每個鉤子應該期待接收一個字符串或字節串對象;字節串對象的編碼由鉤子決定(例如可以是文件系統使用的編碼 UTF-8 或其它編碼),如果鉤子無法解碼參數,它應該引發 [`ImportError`](../library/exceptions.xhtml#ImportError "ImportError")。
如果 [`sys.path_hooks`](../library/sys.xhtml#sys.path_hooks "sys.path_hooks") 迭代結束時沒有返回 [path entry finder](../glossary.xhtml#term-path-entry-finder),則基于路徑的查找器 [`find_spec()`](../library/importlib.xhtml#importlib.machinery.PathFinder.find_spec "importlib.machinery.PathFinder.find_spec") 方法將在 [`sys.path_importer_cache`](../library/sys.xhtml#sys.path_importer_cache "sys.path_importer_cache") 中存入 `None` (表示此路徑條目沒有對應的查找器) 并返回 `None`,表示此 [meta path finder](../glossary.xhtml#term-meta-path-finder) 無法找到該模塊。
如果 [`sys.path_hooks`](../library/sys.xhtml#sys.path_hooks "sys.path_hooks") 中的某個 [path entry hook](../glossary.xhtml#term-path-entry-hook) 可調用對象的返回值 *是* 一個 [path entry finder](../glossary.xhtml#term-path-entry-finder),則以下協議會被用來向查找器請求一個模塊的規格說明,并在加載該模塊時被使用。
當前工作目錄 -- 由一個空字符串表示 -- 的處理方式與 [`sys.path`](../library/sys.xhtml#sys.path "sys.path") 中的其他條目略有不同。 首先,如果發現當前工作目錄不存在,則 [`sys.path_importer_cache`](../library/sys.xhtml#sys.path_importer_cache "sys.path_importer_cache") 中不會存放任何值。 其次,每個模塊查找會對當前工作目錄的值進行全新查找。 第三,由 [`sys.path_importer_cache`](../library/sys.xhtml#sys.path_importer_cache "sys.path_importer_cache") 所使用并由 [`importlib.machinery.PathFinder.find_spec()`](../library/importlib.xhtml#importlib.machinery.PathFinder.find_spec "importlib.machinery.PathFinder.find_spec") 所返回的路徑將是實際的當前工作目錄而非空字符串。
### 5.5.2. 路徑條目查找器協議
為了支持模塊和已初始化包的導入,也為了給命名空間包提供組成部分,路徑條目查找器必須實現 [`find_spec()`](../library/importlib.xhtml#importlib.abc.PathEntryFinder.find_spec "importlib.abc.PathEntryFinder.find_spec") 方法。
[`find_spec()`](../library/importlib.xhtml#importlib.abc.PathEntryFinder.find_spec "importlib.abc.PathEntryFinder.find_spec") 接受兩個參數,即要導入模塊的完整限定名稱,以及(可選的)目標模塊。 `find_spec()` 返回模塊的完全填充好的規格說明。 這個規格說明總是包含“加載器”集合(但有一個例外)。
為了向導入機制提示該規格說明代表一個命名空間的 [portion](../glossary.xhtml#term-portion)。 路徑條目查找器會將規格說明中的 "loader" 設為 `None` 并將 "submodule\_search\_locations" 設為一個包含該部分的列表。
在 3.4 版更改: [`find_spec()`](../library/importlib.xhtml#importlib.abc.PathEntryFinder.find_spec "importlib.abc.PathEntryFinder.find_spec") 替代了 [`find_loader()`](../library/importlib.xhtml#importlib.abc.PathEntryFinder.find_loader "importlib.abc.PathEntryFinder.find_loader") 和 [`find_module()`](../library/importlib.xhtml#importlib.abc.PathEntryFinder.find_module "importlib.abc.PathEntryFinder.find_module"),后兩者現在都已棄用,但會在 `find_spec()` 未定義時被使用。
較舊的路徑條目查找器可能會實現這兩個已棄用的方法中的一個而沒有實現 `find_spec()`。 為保持向后兼容,這兩個方法仍會被接受。 但是,如果在路徑條目查找器上實現了 `find_spec()`,這兩個遺留方法就會被忽略。
[`find_loader()`](../library/importlib.xhtml#importlib.abc.PathEntryFinder.find_loader "importlib.abc.PathEntryFinder.find_loader") 接受一個參數,即被導入模塊的完整限定名稱。 `find_loader()` 會返回一個二元組,其中第一項為加載器,第二項為一個命名空間 [portion](../glossary.xhtml#term-portion)。 當第一項(即加載器)為 `None` 時,這意味著路徑條目查找器雖然沒有指定名稱模塊的加載器,但它知道該路徑條目為指定名稱模塊提供了一個命名空間部分。 這幾乎總是表明一種情況,即 Python 被要求導入一個并不以文件系統中的實體形式存在的命名空間包。 當一個路徑條目查找器返回的加載器為 `None` 時,該二元組返回值的第二項必須為一個序列,不過它也可以為空。
如果 `find_loader()` 所返回加載器的值不為 `None`,則該部分會被忽略,而該加載器會自基于路徑的查找器返回,終止對路徑條目的搜索。
為了向后兼容其他導入協議的實現,許多路徑條目查找器也同樣支持元路徑查找器所支持的傳統 `find_module()` 方法。 但是路徑條目查找器 `find_module()` 方法的調用絕不會帶有 `path` 參數(它們被期望記錄來自對路徑鉤子初始調用的恰當路徑信息)。
路徑條目查找器的 `find_module()` 方法已棄用,因為它不允許路徑條目查找器為命名空間包提供部分。 如果 `find_loader()` 和 `find_module()` 同時存在于一個路徑條目查找器中,導入系統將總是調用 `find_loader()` 而不選擇 `find_module()`。
## 5.6. 替換標準導入系統
替換整個導入系統的最可靠機制是移除 [`sys.meta_path`](../library/sys.xhtml#sys.meta_path "sys.meta_path") 的默認內容,,將其完全替換為自定義的元路徑鉤子。
一個可行的方式是僅改變導入語句的行為而不影響訪問導入系統的其他 API,那么替換內置的 [`__import__()`](../library/functions.xhtml#__import__ "__import__") 函數可能就夠了。 這種技巧也可以在模塊層級上運用,即只在某個模塊內部改變導入語句的行為。
想要選擇性地預先防止在元路徑上從一個鉤子導入某些模塊(而不是完全禁用標準導入系統),直接從 [`find_spec()`](../library/importlib.xhtml#importlib.abc.MetaPathFinder.find_spec "importlib.abc.MetaPathFinder.find_spec") 引發 [`ModuleNotFoundError`](../library/exceptions.xhtml#ModuleNotFoundError "ModuleNotFoundError") 而非返回 `None` 就夠了。 返回后者表示元路徑搜索應當繼續,而引發異常則會立即終止搜索。
## 5.7. Package Relative Imports
Relative imports use leading dots. A single leading dot indicates a relative import, starting with the current package. Two or more leading dots indicate a relative import to the parent(s) of the current package, one level per dot after the first. For example, given the following package layout:
```
package/
__init__.py
subpackage1/
__init__.py
moduleX.py
moduleY.py
subpackage2/
__init__.py
moduleZ.py
moduleA.py
```
In either `subpackage1/moduleX.py` or `subpackage1/__init__.py`, the following are valid relative imports:
```
from .moduleY import spam
from .moduleY import spam as ham
from . import moduleY
from ..subpackage1 import moduleY
from ..subpackage2.moduleZ import eggs
from ..moduleA import foo
```
Absolute imports may use either the `import <>` or `from <> import <>`syntax, but relative imports may only use the second form; the reason for this is that:
```
import XXX.YYY.ZZZ
```
should expose `XXX.YYY.ZZZ` as a usable expression, but .moduleY is not a valid expression.
## 5.8. 有關 \_\_main\_\_ 的特殊事項
對于 Python 的導入系統來說 [`__main__`](../library/__main__.xhtml#module-__main__ "__main__: The environment where the top-level script is run.") 模塊是一個特殊情況。 正如在 [另一節](toplevel_components.xhtml#programs) 中所述,`__main__` 模塊是在解釋器啟動時直接初始化的,與 [`sys`](../library/sys.xhtml#module-sys "sys: Access system-specific parameters and functions.") 和 [`builtins`](../library/builtins.xhtml#module-builtins "builtins: The module that provides the built-in namespace.") 很類似。 但是,與那兩者不同,它并不被嚴格歸類為內置模塊。 這是因為 `__main__` 被初始化的方式依賴于發起調用解釋器所附帶的旗標和其他選項。
### 5.8.1. \_\_main\_\_.\_\_spec\_\_
根據 [`__main__`](../library/__main__.xhtml#module-__main__ "__main__: The environment where the top-level script is run.") 被初始化的方式,`__main__.__spec__` 會被設置相應值或是 `None`。
當 Python 附加 [`-m`](../using/cmdline.xhtml#cmdoption-m) 選項啟動時,`__spec__` 會被設為相應模塊或包的模塊規格說明。 `__spec__` 也會在 `__main__` 模塊作為執行某個目錄,zip 文件或其它 [`sys.path`](../library/sys.xhtml#sys.path "sys.path") 條目的一部分加載時被填充。
在 [其余的情況](../using/cmdline.xhtml#using-on-interface-options) 下 `__main__.__spec__` 會被設為 `None`,因為用于填充 [`__main__`](../library/__main__.xhtml#module-__main__ "__main__: The environment where the top-level script is run.") 的代碼不直接與可導入的模塊相對應:
- 交互型提示
- [`-c`](../using/cmdline.xhtml#cmdoption-c) 選項
- 從 stdin 運行
- 直接從源碼或字節碼文件運行
請注意在最后一種情況中 `__main__.__spec__` 總是為 `None`,*即使* 文件從技術上說可以作為一個模塊被導入。 如果想要讓 [`__main__`](../library/__main__.xhtml#module-__main__ "__main__: The environment where the top-level script is run.") 中的元數據生效,請使用 [`-m`](../using/cmdline.xhtml#cmdoption-m) 開關。
還要注意即使是在 `__main__` 對應于一個可導入模塊且 `__main__.__spec__` 被相應地設定時,它們仍會被視為 *不同的* 模塊。 這是由于以下事實:使用 `if __name__ == "__main__":` 檢測來保護的代碼塊僅會在模塊被用來填充 `__main__` 命名空間時而非普通的導入時被執行。
## 5.9. 開放問題項
XXX 最好是能增加一個圖表。
XXX \* (import\_machinery.rst) 是否要專門增加一節來說明模塊和包的屬性,也許可以擴展或移植數據模型參考頁中的相關條目?
XXX 庫手冊中的 runpy 和 pkgutil 等等應該都在頁面頂端增加指向新的導入系統章節的“另請參閱”鏈接。
XXX 是否要增加關于初始化 `__main__` 的不同方式的更多解釋?
XXX 增加更多有關 `__main__` 怪異/坑人特性的信息 (例如直接從 [**PEP 395**](https://www.python.org/dev/peps/pep-0395) \[https://www.python.org/dev/peps/pep-0395\] 復制)。
## 5.10. 參考文獻
導入機制自 Python 誕生之初至今已發生了很大的變化。 原始的 [包規格說明](https://www.python.org/doc/essays/packages/) \[https://www.python.org/doc/essays/packages/\] 仍然可以查閱,但在撰寫該文檔之后許多相關細節已被修改。
原始的 [`sys.meta_path`](../library/sys.xhtml#sys.meta_path "sys.meta_path") 規格說明見 [**PEP 302**](https://www.python.org/dev/peps/pep-0302) \[https://www.python.org/dev/peps/pep-0302\],后續的擴展說明見 [**PEP 420**](https://www.python.org/dev/peps/pep-0420) \[https://www.python.org/dev/peps/pep-0420\]。
[**PEP 420**](https://www.python.org/dev/peps/pep-0420) \[https://www.python.org/dev/peps/pep-0420\] 為 Python 3.3 引入了 [命名空間包](../glossary.xhtml#term-namespace-package)。 [**PEP 420**](https://www.python.org/dev/peps/pep-0420) \[https://www.python.org/dev/peps/pep-0420\] 還引入了 `find_loader()` 協議作為 `find_module()` 的替代。
[**PEP 366**](https://www.python.org/dev/peps/pep-0366) \[https://www.python.org/dev/peps/pep-0366\] 描述了新增的 `__package__` 屬性,用于在模塊中的顯式相對導入。
[**PEP 328**](https://www.python.org/dev/peps/pep-0328) \[https://www.python.org/dev/peps/pep-0328\] 引入了絕對和顯式相對導入,并初次提出了 `__name__` 語義,最終由 [**PEP 366**](https://www.python.org/dev/peps/pep-0366) \[https://www.python.org/dev/peps/pep-0366\] 為 `__package__` 加入規范描述。
[**PEP 338**](https://www.python.org/dev/peps/pep-0338) \[https://www.python.org/dev/peps/pep-0338\] 定義了將模塊作為腳本執行。
[**PEP 451**](https://www.python.org/dev/peps/pep-0451) \[https://www.python.org/dev/peps/pep-0451\] 在 spec 對象中增加了對每個模塊導入狀態的封裝。 它還將加載器的大部分樣板責任移交回導入機制中。 這些改變允許棄用導入系統中的一些 API 并為查找器和加載器增加一些新的方法。
腳注
[1](#id1)參見 [`types.ModuleType`](../library/types.xhtml#types.ModuleType "types.ModuleType")。
[2](#id2)importlib 實現避免直接使用返回值。 而是通過在 [`sys.modules`](../library/sys.xhtml#sys.modules "sys.modules") 中查找模塊名稱來獲取模塊對象。 這種方式的間接影響是被導入的模塊可能在 [`sys.modules`](../library/sys.xhtml#sys.modules "sys.modules") 中替換其自身。 這屬于具體實現的特定行為,不保證能在其他 Python 實現中起作用。
[3](#id3)在遺留代碼中,有可能在 [`sys.path_importer_cache`](../library/sys.xhtml#sys.path_importer_cache "sys.path_importer_cache") 中找到 [`imp.NullImporter`](../library/imp.xhtml#imp.NullImporter "imp.NullImporter") 的實例。 建議將這些代碼修改為使用 `None` 代替。 詳情參見 [Porting Python code](../whatsnew/3.3.xhtml#portingpythoncode)。
### 導航
- [索引](../genindex.xhtml "總目錄")
- [模塊](../py-modindex.xhtml "Python 模塊索引") |
- [下一頁](expressions.xhtml "6. 表達式") |
- [上一頁](executionmodel.xhtml "4. 執行模型") |
- 
- [Python](https://www.python.org/) ?
- zh\_CN 3.7.3 [文檔](../index.xhtml) ?
- [Python 語言參考](index.xhtml) ?
- $('.inline-search').show(0); |
? [版權所有](../copyright.xhtml) 2001-2019, Python Software Foundation.
Python 軟件基金會是一個非盈利組織。 [請捐助。](https://www.python.org/psf/donations/)
最后更新于 5月 21, 2019. [發現了問題](../bugs.xhtml)?
使用[Sphinx](http://sphinx.pocoo.org/)1.8.4 創建。
- Python文檔內容
- Python 有什么新變化?
- Python 3.7 有什么新變化
- 摘要 - 發布重點
- 新的特性
- 其他語言特性修改
- 新增模塊
- 改進的模塊
- C API 的改變
- 構建的改變
- 性能優化
- 其他 CPython 實現的改變
- 已棄用的 Python 行為
- 已棄用的 Python 模塊、函數和方法
- 已棄用的 C API 函數和類型
- 平臺支持的移除
- API 與特性的移除
- 移除的模塊
- Windows 專屬的改變
- 移植到 Python 3.7
- Python 3.7.1 中的重要變化
- Python 3.7.2 中的重要變化
- Python 3.6 有什么新變化A
- 摘要 - 發布重點
- 新的特性
- 其他語言特性修改
- 新增模塊
- 改進的模塊
- 性能優化
- Build and C API Changes
- 其他改進
- 棄用
- 移除
- 移植到Python 3.6
- Python 3.6.2 中的重要變化
- Python 3.6.4 中的重要變化
- Python 3.6.5 中的重要變化
- Python 3.6.7 中的重要變化
- Python 3.5 有什么新變化
- 摘要 - 發布重點
- 新的特性
- 其他語言特性修改
- 新增模塊
- 改進的模塊
- Other module-level changes
- 性能優化
- Build and C API Changes
- 棄用
- 移除
- Porting to Python 3.5
- Notable changes in Python 3.5.4
- What's New In Python 3.4
- 摘要 - 發布重點
- 新的特性
- 新增模塊
- 改進的模塊
- CPython Implementation Changes
- 棄用
- 移除
- Porting to Python 3.4
- Changed in 3.4.3
- What's New In Python 3.3
- 摘要 - 發布重點
- PEP 405: Virtual Environments
- PEP 420: Implicit Namespace Packages
- PEP 3118: New memoryview implementation and buffer protocol documentation
- PEP 393: Flexible String Representation
- PEP 397: Python Launcher for Windows
- PEP 3151: Reworking the OS and IO exception hierarchy
- PEP 380: Syntax for Delegating to a Subgenerator
- PEP 409: Suppressing exception context
- PEP 414: Explicit Unicode literals
- PEP 3155: Qualified name for classes and functions
- PEP 412: Key-Sharing Dictionary
- PEP 362: Function Signature Object
- PEP 421: Adding sys.implementation
- Using importlib as the Implementation of Import
- 其他語言特性修改
- A Finer-Grained Import Lock
- Builtin functions and types
- 新增模塊
- 改進的模塊
- 性能優化
- Build and C API Changes
- 棄用
- Porting to Python 3.3
- What's New In Python 3.2
- PEP 384: Defining a Stable ABI
- PEP 389: Argparse Command Line Parsing Module
- PEP 391: Dictionary Based Configuration for Logging
- PEP 3148: The concurrent.futures module
- PEP 3147: PYC Repository Directories
- PEP 3149: ABI Version Tagged .so Files
- PEP 3333: Python Web Server Gateway Interface v1.0.1
- 其他語言特性修改
- New, Improved, and Deprecated Modules
- 多線程
- 性能優化
- Unicode
- Codecs
- 文檔
- IDLE
- Code Repository
- Build and C API Changes
- Porting to Python 3.2
- What's New In Python 3.1
- PEP 372: Ordered Dictionaries
- PEP 378: Format Specifier for Thousands Separator
- 其他語言特性修改
- New, Improved, and Deprecated Modules
- 性能優化
- IDLE
- Build and C API Changes
- Porting to Python 3.1
- What's New In Python 3.0
- Common Stumbling Blocks
- Overview Of Syntax Changes
- Changes Already Present In Python 2.6
- Library Changes
- PEP 3101: A New Approach To String Formatting
- Changes To Exceptions
- Miscellaneous Other Changes
- Build and C API Changes
- 性能
- Porting To Python 3.0
- What's New in Python 2.7
- The Future for Python 2.x
- Changes to the Handling of Deprecation Warnings
- Python 3.1 Features
- PEP 372: Adding an Ordered Dictionary to collections
- PEP 378: Format Specifier for Thousands Separator
- PEP 389: The argparse Module for Parsing Command Lines
- PEP 391: Dictionary-Based Configuration For Logging
- PEP 3106: Dictionary Views
- PEP 3137: The memoryview Object
- 其他語言特性修改
- New and Improved Modules
- Build and C API Changes
- Other Changes and Fixes
- Porting to Python 2.7
- New Features Added to Python 2.7 Maintenance Releases
- Acknowledgements
- Python 2.6 有什么新變化
- Python 3.0
- Changes to the Development Process
- PEP 343: The 'with' statement
- PEP 366: Explicit Relative Imports From a Main Module
- PEP 370: Per-user site-packages Directory
- PEP 371: The multiprocessing Package
- PEP 3101: Advanced String Formatting
- PEP 3105: print As a Function
- PEP 3110: Exception-Handling Changes
- PEP 3112: Byte Literals
- PEP 3116: New I/O Library
- PEP 3118: Revised Buffer Protocol
- PEP 3119: Abstract Base Classes
- PEP 3127: Integer Literal Support and Syntax
- PEP 3129: Class Decorators
- PEP 3141: A Type Hierarchy for Numbers
- 其他語言特性修改
- New and Improved Modules
- Deprecations and Removals
- Build and C API Changes
- Porting to Python 2.6
- Acknowledgements
- What's New in Python 2.5
- PEP 308: Conditional Expressions
- PEP 309: Partial Function Application
- PEP 314: Metadata for Python Software Packages v1.1
- PEP 328: Absolute and Relative Imports
- PEP 338: Executing Modules as Scripts
- PEP 341: Unified try/except/finally
- PEP 342: New Generator Features
- PEP 343: The 'with' statement
- PEP 352: Exceptions as New-Style Classes
- PEP 353: Using ssize_t as the index type
- PEP 357: The 'index' method
- 其他語言特性修改
- New, Improved, and Removed Modules
- Build and C API Changes
- Porting to Python 2.5
- Acknowledgements
- What's New in Python 2.4
- PEP 218: Built-In Set Objects
- PEP 237: Unifying Long Integers and Integers
- PEP 289: Generator Expressions
- PEP 292: Simpler String Substitutions
- PEP 318: Decorators for Functions and Methods
- PEP 322: Reverse Iteration
- PEP 324: New subprocess Module
- PEP 327: Decimal Data Type
- PEP 328: Multi-line Imports
- PEP 331: Locale-Independent Float/String Conversions
- 其他語言特性修改
- New, Improved, and Deprecated Modules
- Build and C API Changes
- Porting to Python 2.4
- Acknowledgements
- What's New in Python 2.3
- PEP 218: A Standard Set Datatype
- PEP 255: Simple Generators
- PEP 263: Source Code Encodings
- PEP 273: Importing Modules from ZIP Archives
- PEP 277: Unicode file name support for Windows NT
- PEP 278: Universal Newline Support
- PEP 279: enumerate()
- PEP 282: The logging Package
- PEP 285: A Boolean Type
- PEP 293: Codec Error Handling Callbacks
- PEP 301: Package Index and Metadata for Distutils
- PEP 302: New Import Hooks
- PEP 305: Comma-separated Files
- PEP 307: Pickle Enhancements
- Extended Slices
- 其他語言特性修改
- New, Improved, and Deprecated Modules
- Pymalloc: A Specialized Object Allocator
- Build and C API Changes
- Other Changes and Fixes
- Porting to Python 2.3
- Acknowledgements
- What's New in Python 2.2
- 概述
- PEPs 252 and 253: Type and Class Changes
- PEP 234: Iterators
- PEP 255: Simple Generators
- PEP 237: Unifying Long Integers and Integers
- PEP 238: Changing the Division Operator
- Unicode Changes
- PEP 227: Nested Scopes
- New and Improved Modules
- Interpreter Changes and Fixes
- Other Changes and Fixes
- Acknowledgements
- What's New in Python 2.1
- 概述
- PEP 227: Nested Scopes
- PEP 236: future Directives
- PEP 207: Rich Comparisons
- PEP 230: Warning Framework
- PEP 229: New Build System
- PEP 205: Weak References
- PEP 232: Function Attributes
- PEP 235: Importing Modules on Case-Insensitive Platforms
- PEP 217: Interactive Display Hook
- PEP 208: New Coercion Model
- PEP 241: Metadata in Python Packages
- New and Improved Modules
- Other Changes and Fixes
- Acknowledgements
- What's New in Python 2.0
- 概述
- What About Python 1.6?
- New Development Process
- Unicode
- 列表推導式
- Augmented Assignment
- 字符串的方法
- Garbage Collection of Cycles
- Other Core Changes
- Porting to 2.0
- Extending/Embedding Changes
- Distutils: Making Modules Easy to Install
- XML Modules
- Module changes
- New modules
- IDLE Improvements
- Deleted and Deprecated Modules
- Acknowledgements
- 更新日志
- Python 下一版
- Python 3.7.3 最終版
- Python 3.7.3 發布候選版 1
- Python 3.7.2 最終版
- Python 3.7.2 發布候選版 1
- Python 3.7.1 最終版
- Python 3.7.1 RC 2版本
- Python 3.7.1 發布候選版 1
- Python 3.7.0 正式版
- Python 3.7.0 release candidate 1
- Python 3.7.0 beta 5
- Python 3.7.0 beta 4
- Python 3.7.0 beta 3
- Python 3.7.0 beta 2
- Python 3.7.0 beta 1
- Python 3.7.0 alpha 4
- Python 3.7.0 alpha 3
- Python 3.7.0 alpha 2
- Python 3.7.0 alpha 1
- Python 3.6.6 final
- Python 3.6.6 RC 1
- Python 3.6.5 final
- Python 3.6.5 release candidate 1
- Python 3.6.4 final
- Python 3.6.4 release candidate 1
- Python 3.6.3 final
- Python 3.6.3 release candidate 1
- Python 3.6.2 final
- Python 3.6.2 release candidate 2
- Python 3.6.2 release candidate 1
- Python 3.6.1 final
- Python 3.6.1 release candidate 1
- Python 3.6.0 final
- Python 3.6.0 release candidate 2
- Python 3.6.0 release candidate 1
- Python 3.6.0 beta 4
- Python 3.6.0 beta 3
- Python 3.6.0 beta 2
- Python 3.6.0 beta 1
- Python 3.6.0 alpha 4
- Python 3.6.0 alpha 3
- Python 3.6.0 alpha 2
- Python 3.6.0 alpha 1
- Python 3.5.5 final
- Python 3.5.5 release candidate 1
- Python 3.5.4 final
- Python 3.5.4 release candidate 1
- Python 3.5.3 final
- Python 3.5.3 release candidate 1
- Python 3.5.2 final
- Python 3.5.2 release candidate 1
- Python 3.5.1 final
- Python 3.5.1 release candidate 1
- Python 3.5.0 final
- Python 3.5.0 release candidate 4
- Python 3.5.0 release candidate 3
- Python 3.5.0 release candidate 2
- Python 3.5.0 release candidate 1
- Python 3.5.0 beta 4
- Python 3.5.0 beta 3
- Python 3.5.0 beta 2
- Python 3.5.0 beta 1
- Python 3.5.0 alpha 4
- Python 3.5.0 alpha 3
- Python 3.5.0 alpha 2
- Python 3.5.0 alpha 1
- Python 教程
- 課前甜點
- 使用 Python 解釋器
- 調用解釋器
- 解釋器的運行環境
- Python 的非正式介紹
- Python 作為計算器使用
- 走向編程的第一步
- 其他流程控制工具
- if 語句
- for 語句
- range() 函數
- break 和 continue 語句,以及循環中的 else 子句
- pass 語句
- 定義函數
- 函數定義的更多形式
- 小插曲:編碼風格
- 數據結構
- 列表的更多特性
- del 語句
- 元組和序列
- 集合
- 字典
- 循環的技巧
- 深入條件控制
- 序列和其它類型的比較
- 模塊
- 有關模塊的更多信息
- 標準模塊
- dir() 函數
- 包
- 輸入輸出
- 更漂亮的輸出格式
- 讀寫文件
- 錯誤和異常
- 語法錯誤
- 異常
- 處理異常
- 拋出異常
- 用戶自定義異常
- 定義清理操作
- 預定義的清理操作
- 類
- 名稱和對象
- Python 作用域和命名空間
- 初探類
- 補充說明
- 繼承
- 私有變量
- 雜項說明
- 迭代器
- 生成器
- 生成器表達式
- 標準庫簡介
- 操作系統接口
- 文件通配符
- 命令行參數
- 錯誤輸出重定向和程序終止
- 字符串模式匹配
- 數學
- 互聯網訪問
- 日期和時間
- 數據壓縮
- 性能測量
- 質量控制
- 自帶電池
- 標準庫簡介 —— 第二部分
- 格式化輸出
- 模板
- 使用二進制數據記錄格式
- 多線程
- 日志
- 弱引用
- 用于操作列表的工具
- 十進制浮點運算
- 虛擬環境和包
- 概述
- 創建虛擬環境
- 使用pip管理包
- 接下來?
- 交互式編輯和編輯歷史
- Tab 補全和編輯歷史
- 默認交互式解釋器的替代品
- 浮點算術:爭議和限制
- 表示性錯誤
- 附錄
- 交互模式
- 安裝和使用 Python
- 命令行與環境
- 命令行
- 環境變量
- 在Unix平臺中使用Python
- 獲取最新版本的Python
- 構建Python
- 與Python相關的路徑和文件
- 雜項
- 編輯器和集成開發環境
- 在Windows上使用 Python
- 完整安裝程序
- Microsoft Store包
- nuget.org 安裝包
- 可嵌入的包
- 替代捆綁包
- 配置Python
- 適用于Windows的Python啟動器
- 查找模塊
- 附加模塊
- 在Windows上編譯Python
- 其他平臺
- 在蘋果系統上使用 Python
- 獲取和安裝 MacPython
- IDE
- 安裝額外的 Python 包
- Mac 上的圖形界面編程
- 在 Mac 上分發 Python 應用程序
- 其他資源
- Python 語言參考
- 概述
- 其他實現
- 標注
- 詞法分析
- 行結構
- 其他形符
- 標識符和關鍵字
- 字面值
- 運算符
- 分隔符
- 數據模型
- 對象、值與類型
- 標準類型層級結構
- 特殊方法名稱
- 協程
- 執行模型
- 程序的結構
- 命名與綁定
- 異常
- 導入系統
- importlib
- 包
- 搜索
- 加載
- 基于路徑的查找器
- 替換標準導入系統
- Package Relative Imports
- 有關 main 的特殊事項
- 開放問題項
- 參考文獻
- 表達式
- 算術轉換
- 原子
- 原型
- await 表達式
- 冪運算符
- 一元算術和位運算
- 二元算術運算符
- 移位運算
- 二元位運算
- 比較運算
- 布爾運算
- 條件表達式
- lambda 表達式
- 表達式列表
- 求值順序
- 運算符優先級
- 簡單語句
- 表達式語句
- 賦值語句
- assert 語句
- pass 語句
- del 語句
- return 語句
- yield 語句
- raise 語句
- break 語句
- continue 語句
- import 語句
- global 語句
- nonlocal 語句
- 復合語句
- if 語句
- while 語句
- for 語句
- try 語句
- with 語句
- 函數定義
- 類定義
- 協程
- 最高層級組件
- 完整的 Python 程序
- 文件輸入
- 交互式輸入
- 表達式輸入
- 完整的語法規范
- Python 標準庫
- 概述
- 可用性注釋
- 內置函數
- 內置常量
- 由 site 模塊添加的常量
- 內置類型
- 邏輯值檢測
- 布爾運算 — and, or, not
- 比較
- 數字類型 — int, float, complex
- 迭代器類型
- 序列類型 — list, tuple, range
- 文本序列類型 — str
- 二進制序列類型 — bytes, bytearray, memoryview
- 集合類型 — set, frozenset
- 映射類型 — dict
- 上下文管理器類型
- 其他內置類型
- 特殊屬性
- 內置異常
- 基類
- 具體異常
- 警告
- 異常層次結構
- 文本處理服務
- string — 常見的字符串操作
- re — 正則表達式操作
- 模塊 difflib 是一個計算差異的助手
- textwrap — Text wrapping and filling
- unicodedata — Unicode 數據庫
- stringprep — Internet String Preparation
- readline — GNU readline interface
- rlcompleter — GNU readline的完成函數
- 二進制數據服務
- struct — Interpret bytes as packed binary data
- codecs — Codec registry and base classes
- 數據類型
- datetime — 基礎日期/時間數據類型
- calendar — General calendar-related functions
- collections — 容器數據類型
- collections.abc — 容器的抽象基類
- heapq — 堆隊列算法
- bisect — Array bisection algorithm
- array — Efficient arrays of numeric values
- weakref — 弱引用
- types — Dynamic type creation and names for built-in types
- copy — 淺層 (shallow) 和深層 (deep) 復制操作
- pprint — 數據美化輸出
- reprlib — Alternate repr() implementation
- enum — Support for enumerations
- 數字和數學模塊
- numbers — 數字的抽象基類
- math — 數學函數
- cmath — Mathematical functions for complex numbers
- decimal — 十進制定點和浮點運算
- fractions — 分數
- random — 生成偽隨機數
- statistics — Mathematical statistics functions
- 函數式編程模塊
- itertools — 為高效循環而創建迭代器的函數
- functools — 高階函數和可調用對象上的操作
- operator — 標準運算符替代函數
- 文件和目錄訪問
- pathlib — 面向對象的文件系統路徑
- os.path — 常見路徑操作
- fileinput — Iterate over lines from multiple input streams
- stat — Interpreting stat() results
- filecmp — File and Directory Comparisons
- tempfile — Generate temporary files and directories
- glob — Unix style pathname pattern expansion
- fnmatch — Unix filename pattern matching
- linecache — Random access to text lines
- shutil — High-level file operations
- macpath — Mac OS 9 路徑操作函數
- 數據持久化
- pickle —— Python 對象序列化
- copyreg — Register pickle support functions
- shelve — Python object persistence
- marshal — Internal Python object serialization
- dbm — Interfaces to Unix “databases”
- sqlite3 — SQLite 數據庫 DB-API 2.0 接口模塊
- 數據壓縮和存檔
- zlib — 與 gzip 兼容的壓縮
- gzip — 對 gzip 格式的支持
- bz2 — 對 bzip2 壓縮算法的支持
- lzma — 用 LZMA 算法壓縮
- zipfile — 在 ZIP 歸檔中工作
- tarfile — Read and write tar archive files
- 文件格式
- csv — CSV 文件讀寫
- configparser — Configuration file parser
- netrc — netrc file processing
- xdrlib — Encode and decode XDR data
- plistlib — Generate and parse Mac OS X .plist files
- 加密服務
- hashlib — 安全哈希與消息摘要
- hmac — 基于密鑰的消息驗證
- secrets — Generate secure random numbers for managing secrets
- 通用操作系統服務
- os — 操作系統接口模塊
- io — 處理流的核心工具
- time — 時間的訪問和轉換
- argparse — 命令行選項、參數和子命令解析器
- getopt — C-style parser for command line options
- 模塊 logging — Python 的日志記錄工具
- logging.config — 日志記錄配置
- logging.handlers — Logging handlers
- getpass — 便攜式密碼輸入工具
- curses — 終端字符單元顯示的處理
- curses.textpad — Text input widget for curses programs
- curses.ascii — Utilities for ASCII characters
- curses.panel — A panel stack extension for curses
- platform — Access to underlying platform's identifying data
- errno — Standard errno system symbols
- ctypes — Python 的外部函數庫
- 并發執行
- threading — 基于線程的并行
- multiprocessing — 基于進程的并行
- concurrent 包
- concurrent.futures — 啟動并行任務
- subprocess — 子進程管理
- sched — 事件調度器
- queue — 一個同步的隊列類
- _thread — 底層多線程 API
- _dummy_thread — _thread 的替代模塊
- dummy_threading — 可直接替代 threading 模塊。
- contextvars — Context Variables
- Context Variables
- Manual Context Management
- asyncio support
- 網絡和進程間通信
- asyncio — 異步 I/O
- socket — 底層網絡接口
- ssl — TLS/SSL wrapper for socket objects
- select — Waiting for I/O completion
- selectors — 高級 I/O 復用庫
- asyncore — 異步socket處理器
- asynchat — 異步 socket 指令/響應 處理器
- signal — Set handlers for asynchronous events
- mmap — Memory-mapped file support
- 互聯網數據處理
- email — 電子郵件與 MIME 處理包
- json — JSON 編碼和解碼器
- mailcap — Mailcap file handling
- mailbox — Manipulate mailboxes in various formats
- mimetypes — Map filenames to MIME types
- base64 — Base16, Base32, Base64, Base85 數據編碼
- binhex — 對binhex4文件進行編碼和解碼
- binascii — 二進制和 ASCII 碼互轉
- quopri — Encode and decode MIME quoted-printable data
- uu — Encode and decode uuencode files
- 結構化標記處理工具
- html — 超文本標記語言支持
- html.parser — 簡單的 HTML 和 XHTML 解析器
- html.entities — HTML 一般實體的定義
- XML處理模塊
- xml.etree.ElementTree — The ElementTree XML API
- xml.dom — The Document Object Model API
- xml.dom.minidom — Minimal DOM implementation
- xml.dom.pulldom — Support for building partial DOM trees
- xml.sax — Support for SAX2 parsers
- xml.sax.handler — Base classes for SAX handlers
- xml.sax.saxutils — SAX Utilities
- xml.sax.xmlreader — Interface for XML parsers
- xml.parsers.expat — Fast XML parsing using Expat
- 互聯網協議和支持
- webbrowser — 方便的Web瀏覽器控制器
- cgi — Common Gateway Interface support
- cgitb — Traceback manager for CGI scripts
- wsgiref — WSGI Utilities and Reference Implementation
- urllib — URL 處理模塊
- urllib.request — 用于打開 URL 的可擴展庫
- urllib.response — Response classes used by urllib
- urllib.parse — Parse URLs into components
- urllib.error — Exception classes raised by urllib.request
- urllib.robotparser — Parser for robots.txt
- http — HTTP 模塊
- http.client — HTTP協議客戶端
- ftplib — FTP protocol client
- poplib — POP3 protocol client
- imaplib — IMAP4 protocol client
- nntplib — NNTP protocol client
- smtplib —SMTP協議客戶端
- smtpd — SMTP Server
- telnetlib — Telnet client
- uuid — UUID objects according to RFC 4122
- socketserver — A framework for network servers
- http.server — HTTP 服務器
- http.cookies — HTTP state management
- http.cookiejar — Cookie handling for HTTP clients
- xmlrpc — XMLRPC 服務端與客戶端模塊
- xmlrpc.client — XML-RPC client access
- xmlrpc.server — Basic XML-RPC servers
- ipaddress — IPv4/IPv6 manipulation library
- 多媒體服務
- audioop — Manipulate raw audio data
- aifc — Read and write AIFF and AIFC files
- sunau — 讀寫 Sun AU 文件
- wave — 讀寫WAV格式文件
- chunk — Read IFF chunked data
- colorsys — Conversions between color systems
- imghdr — 推測圖像類型
- sndhdr — 推測聲音文件的類型
- ossaudiodev — Access to OSS-compatible audio devices
- 國際化
- gettext — 多語種國際化服務
- locale — 國際化服務
- 程序框架
- turtle — 海龜繪圖
- cmd — 支持面向行的命令解釋器
- shlex — Simple lexical analysis
- Tk圖形用戶界面(GUI)
- tkinter — Tcl/Tk的Python接口
- tkinter.ttk — Tk themed widgets
- tkinter.tix — Extension widgets for Tk
- tkinter.scrolledtext — 滾動文字控件
- IDLE
- 其他圖形用戶界面(GUI)包
- 開發工具
- typing — 類型標注支持
- pydoc — Documentation generator and online help system
- doctest — Test interactive Python examples
- unittest — 單元測試框架
- unittest.mock — mock object library
- unittest.mock 上手指南
- 2to3 - 自動將 Python 2 代碼轉為 Python 3 代碼
- test — Regression tests package for Python
- test.support — Utilities for the Python test suite
- test.support.script_helper — Utilities for the Python execution tests
- 調試和分析
- bdb — Debugger framework
- faulthandler — Dump the Python traceback
- pdb — The Python Debugger
- The Python Profilers
- timeit — 測量小代碼片段的執行時間
- trace — Trace or track Python statement execution
- tracemalloc — Trace memory allocations
- 軟件打包和分發
- distutils — 構建和安裝 Python 模塊
- ensurepip — Bootstrapping the pip installer
- venv — 創建虛擬環境
- zipapp — Manage executable Python zip archives
- Python運行時服務
- sys — 系統相關的參數和函數
- sysconfig — Provide access to Python's configuration information
- builtins — 內建對象
- main — 頂層腳本環境
- warnings — Warning control
- dataclasses — 數據類
- contextlib — Utilities for with-statement contexts
- abc — 抽象基類
- atexit — 退出處理器
- traceback — Print or retrieve a stack traceback
- future — Future 語句定義
- gc — 垃圾回收器接口
- inspect — 檢查對象
- site — Site-specific configuration hook
- 自定義 Python 解釋器
- code — Interpreter base classes
- codeop — Compile Python code
- 導入模塊
- zipimport — Import modules from Zip archives
- pkgutil — Package extension utility
- modulefinder — 查找腳本使用的模塊
- runpy — Locating and executing Python modules
- importlib — The implementation of import
- Python 語言服務
- parser — Access Python parse trees
- ast — 抽象語法樹
- symtable — Access to the compiler's symbol tables
- symbol — 與 Python 解析樹一起使用的常量
- token — 與Python解析樹一起使用的常量
- keyword — 檢驗Python關鍵字
- tokenize — Tokenizer for Python source
- tabnanny — 模糊縮進檢測
- pyclbr — Python class browser support
- py_compile — Compile Python source files
- compileall — Byte-compile Python libraries
- dis — Python 字節碼反匯編器
- pickletools — Tools for pickle developers
- 雜項服務
- formatter — Generic output formatting
- Windows系統相關模塊
- msilib — Read and write Microsoft Installer files
- msvcrt — Useful routines from the MS VC++ runtime
- winreg — Windows 注冊表訪問
- winsound — Sound-playing interface for Windows
- Unix 專有服務
- posix — The most common POSIX system calls
- pwd — 用戶密碼數據庫
- spwd — The shadow password database
- grp — The group database
- crypt — Function to check Unix passwords
- termios — POSIX style tty control
- tty — 終端控制功能
- pty — Pseudo-terminal utilities
- fcntl — The fcntl and ioctl system calls
- pipes — Interface to shell pipelines
- resource — Resource usage information
- nis — Interface to Sun's NIS (Yellow Pages)
- Unix syslog 庫例程
- 被取代的模塊
- optparse — Parser for command line options
- imp — Access the import internals
- 未創建文檔的模塊
- 平臺特定模塊
- 擴展和嵌入 Python 解釋器
- 推薦的第三方工具
- 不使用第三方工具創建擴展
- 使用 C 或 C++ 擴展 Python
- 自定義擴展類型:教程
- 定義擴展類型:已分類主題
- 構建C/C++擴展
- 在Windows平臺編譯C和C++擴展
- 在更大的應用程序中嵌入 CPython 運行時
- Embedding Python in Another Application
- Python/C API 參考手冊
- 概述
- 代碼標準
- 包含文件
- 有用的宏
- 對象、類型和引用計數
- 異常
- 嵌入Python
- 調試構建
- 穩定的應用程序二進制接口
- The Very High Level Layer
- Reference Counting
- 異常處理
- Printing and clearing
- 拋出異常
- Issuing warnings
- Querying the error indicator
- Signal Handling
- Exception Classes
- Exception Objects
- Unicode Exception Objects
- Recursion Control
- 標準異常
- 標準警告類別
- 工具
- 操作系統實用程序
- 系統功能
- 過程控制
- 導入模塊
- Data marshalling support
- 語句解釋及變量編譯
- 字符串轉換與格式化
- 反射
- 編解碼器注冊與支持功能
- 抽象對象層
- Object Protocol
- 數字協議
- Sequence Protocol
- Mapping Protocol
- 迭代器協議
- 緩沖協議
- Old Buffer Protocol
- 具體的對象層
- 基本對象
- 數值對象
- 序列對象
- 容器對象
- 函數對象
- 其他對象
- Initialization, Finalization, and Threads
- 在Python初始化之前
- 全局配置變量
- Initializing and finalizing the interpreter
- Process-wide parameters
- Thread State and the Global Interpreter Lock
- Sub-interpreter support
- Asynchronous Notifications
- Profiling and Tracing
- Advanced Debugger Support
- Thread Local Storage Support
- 內存管理
- 概述
- 原始內存接口
- Memory Interface
- 對象分配器
- 默認內存分配器
- Customize Memory Allocators
- The pymalloc allocator
- tracemalloc C API
- 示例
- 對象實現支持
- 在堆中分配對象
- Common Object Structures
- Type 對象
- Number Object Structures
- Mapping Object Structures
- Sequence Object Structures
- Buffer Object Structures
- Async Object Structures
- 使對象類型支持循環垃圾回收
- API 和 ABI 版本管理
- 分發 Python 模塊
- 關鍵術語
- 開源許可與協作
- 安裝工具
- 閱讀指南
- 我該如何...?
- ...為我的項目選擇一個名字?
- ...創建和分發二進制擴展?
- 安裝 Python 模塊
- 關鍵術語
- 基本使用
- 我應如何 ...?
- ... 在 Python 3.4 之前的 Python 版本中安裝 pip ?
- ... 只為當前用戶安裝軟件包?
- ... 安裝科學計算類 Python 軟件包?
- ... 使用并行安裝的多個 Python 版本?
- 常見的安裝問題
- 在 Linux 的系統 Python 版本上安裝
- 未安裝 pip
- 安裝二進制編譯擴展
- Python 常用指引
- 將 Python 2 代碼遷移到 Python 3
- 簡要說明
- 詳情
- 將擴展模塊移植到 Python 3
- 條件編譯
- 對象API的更改
- 模塊初始化和狀態
- CObject 替換為 Capsule
- 其他選項
- Curses Programming with Python
- What is curses?
- Starting and ending a curses application
- Windows and Pads
- Displaying Text
- User Input
- For More Information
- 實現描述器
- 摘要
- 定義和簡介
- 描述器協議
- 發起調用描述符
- 描述符示例
- Properties
- 函數和方法
- Static Methods and Class Methods
- 函數式編程指引
- 概述
- 迭代器
- 生成器表達式和列表推導式
- 生成器
- 內置函數
- itertools 模塊
- The functools module
- Small functions and the lambda expression
- Revision History and Acknowledgements
- 引用文獻
- 日志 HOWTO
- 日志基礎教程
- 進階日志教程
- 日志級別
- 有用的處理程序
- 記錄日志中引發的異常
- 使用任意對象作為消息
- 優化
- 日志操作手冊
- 在多個模塊中使用日志
- 在多線程中使用日志
- 使用多個日志處理器和多種格式化
- 在多個地方記錄日志
- 日志服務器配置示例
- 處理日志處理器的阻塞
- Sending and receiving logging events across a network
- Adding contextual information to your logging output
- Logging to a single file from multiple processes
- Using file rotation
- Use of alternative formatting styles
- Customizing LogRecord
- Subclassing QueueHandler - a ZeroMQ example
- Subclassing QueueListener - a ZeroMQ example
- An example dictionary-based configuration
- Using a rotator and namer to customize log rotation processing
- A more elaborate multiprocessing example
- Inserting a BOM into messages sent to a SysLogHandler
- Implementing structured logging
- Customizing handlers with dictConfig()
- Using particular formatting styles throughout your application
- Configuring filters with dictConfig()
- Customized exception formatting
- Speaking logging messages
- Buffering logging messages and outputting them conditionally
- Formatting times using UTC (GMT) via configuration
- Using a context manager for selective logging
- 正則表達式HOWTO
- 概述
- 簡單模式
- 使用正則表達式
- 更多模式能力
- 修改字符串
- 常見問題
- 反饋
- 套接字編程指南
- 套接字
- 創建套接字
- 使用一個套接字
- 斷開連接
- 非阻塞的套接字
- 排序指南
- 基本排序
- 關鍵函數
- Operator 模塊函數
- 升序和降序
- 排序穩定性和排序復雜度
- 使用裝飾-排序-去裝飾的舊方法
- 使用 cmp 參數的舊方法
- 其它
- Unicode 指南
- Unicode 概述
- Python's Unicode Support
- Reading and Writing Unicode Data
- Acknowledgements
- 如何使用urllib包獲取網絡資源
- 概述
- Fetching URLs
- 處理異常
- info and geturl
- Openers and Handlers
- Basic Authentication
- Proxies
- Sockets and Layers
- 腳注
- Argparse 教程
- 概念
- 基礎
- 位置參數介紹
- Introducing Optional arguments
- Combining Positional and Optional arguments
- Getting a little more advanced
- Conclusion
- ipaddress模塊介紹
- 創建 Address/Network/Interface 對象
- 審查 Address/Network/Interface 對象
- Network 作為 Address 列表
- 比較
- 將IP地址與其他模塊一起使用
- 實例創建失敗時獲取更多詳細信息
- Argument Clinic How-To
- The Goals Of Argument Clinic
- Basic Concepts And Usage
- Converting Your First Function
- Advanced Topics
- 使用 DTrace 和 SystemTap 檢測CPython
- Enabling the static markers
- Static DTrace probes
- Static SystemTap markers
- Available static markers
- SystemTap Tapsets
- 示例
- Python 常見問題
- Python常見問題
- 一般信息
- 現實世界中的 Python
- 編程常見問題
- 一般問題
- 核心語言
- 數字和字符串
- 性能
- 序列(元組/列表)
- 對象
- 模塊
- 設計和歷史常見問題
- 為什么Python使用縮進來分組語句?
- 為什么簡單的算術運算得到奇怪的結果?
- 為什么浮點計算不準確?
- 為什么Python字符串是不可變的?
- 為什么必須在方法定義和調用中顯式使用“self”?
- 為什么不能在表達式中賦值?
- 為什么Python對某些功能(例如list.index())使用方法來實現,而其他功能(例如len(List))使用函數實現?
- 為什么 join()是一個字符串方法而不是列表或元組方法?
- 異常有多快?
- 為什么Python中沒有switch或case語句?
- 難道不能在解釋器中模擬線程,而非得依賴特定于操作系統的線程實現嗎?
- 為什么lambda表達式不能包含語句?
- 可以將Python編譯為機器代碼,C或其他語言嗎?
- Python如何管理內存?
- 為什么CPython不使用更傳統的垃圾回收方案?
- CPython退出時為什么不釋放所有內存?
- 為什么有單獨的元組和列表數據類型?
- 列表是如何在CPython中實現的?
- 字典是如何在CPython中實現的?
- 為什么字典key必須是不可變的?
- 為什么 list.sort() 沒有返回排序列表?
- 如何在Python中指定和實施接口規范?
- 為什么沒有goto?
- 為什么原始字符串(r-strings)不能以反斜杠結尾?
- 為什么Python沒有屬性賦值的“with”語句?
- 為什么 if/while/def/class語句需要冒號?
- 為什么Python在列表和元組的末尾允許使用逗號?
- 代碼庫和插件 FAQ
- 通用的代碼庫問題
- 通用任務
- 線程相關
- 輸入輸出
- 網絡 / Internet 編程
- 數據庫
- 數學和數字
- 擴展/嵌入常見問題
- 可以使用C語言中創建自己的函數嗎?
- 可以使用C++語言中創建自己的函數嗎?
- C很難寫,有沒有其他選擇?
- 如何從C執行任意Python語句?
- 如何從C中評估任意Python表達式?
- 如何從Python對象中提取C的值?
- 如何使用Py_BuildValue()創建任意長度的元組?
- 如何從C調用對象的方法?
- 如何捕獲PyErr_Print()(或打印到stdout / stderr的任何內容)的輸出?
- 如何從C訪問用Python編寫的模塊?
- 如何從Python接口到C ++對象?
- 我使用Setup文件添加了一個模塊,為什么make失敗了?
- 如何調試擴展?
- 我想在Linux系統上編譯一個Python模塊,但是缺少一些文件。為什么?
- 如何區分“輸入不完整”和“輸入無效”?
- 如何找到未定義的g++符號__builtin_new或__pure_virtual?
- 能否創建一個對象類,其中部分方法在C中實現,而其他方法在Python中實現(例如通過繼承)?
- Python在Windows上的常見問題
- 我怎樣在Windows下運行一個Python程序?
- 我怎么讓 Python 腳本可執行?
- 為什么有時候 Python 程序會啟動緩慢?
- 我怎樣使用Python腳本制作可執行文件?
- *.pyd 文件和DLL文件相同嗎?
- 我怎樣將Python嵌入一個Windows程序?
- 如何讓編輯器不要在我的 Python 源代碼中插入 tab ?
- 如何在不阻塞的情況下檢查按鍵?
- 圖形用戶界面(GUI)常見問題
- 圖形界面常見問題
- Python 是否有平臺無關的圖形界面工具包?
- 有哪些Python的GUI工具是某個平臺專用的?
- 有關Tkinter的問題
- “為什么我的電腦上安裝了 Python ?”
- 什么是Python?
- 為什么我的電腦上安裝了 Python ?
- 我能刪除 Python 嗎?
- 術語對照表
- 文檔說明
- Python 文檔貢獻者
- 解決 Bug
- 文檔錯誤
- 使用 Python 的錯誤追蹤系統
- 開始為 Python 貢獻您的知識
- 版權
- 歷史和許可證
- 軟件歷史
- 訪問Python或以其他方式使用Python的條款和條件
- Python 3.7.3 的 PSF 許可協議
- Python 2.0 的 BeOpen.com 許可協議
- Python 1.6.1 的 CNRI 許可協議
- Python 0.9.0 至 1.2 的 CWI 許可協議
- 集成軟件的許可和認可
- Mersenne Twister
- 套接字
- Asynchronous socket services
- Cookie management
- Execution tracing
- UUencode and UUdecode functions
- XML Remote Procedure Calls
- test_epoll
- Select kqueue
- SipHash24
- strtod and dtoa
- OpenSSL
- expat
- libffi
- zlib
- cfuhash
- libmpdec