# `pkgutil` --- 套件擴充工具程式

原始碼：Lib/pkgutil.py

此模組提供了引入系統 (import system) 的工具程式，特別是套件相關支援。

class pkgutil.ModuleInfo(module_finder, name, ispkg)

  一個包含模組資訊之簡短摘要的附名元組 (namedtuple)。

  在 3.6 版被加入.

pkgutil.extend_path(path, name)

  擴充組成一個套件之模組的搜尋路徑。預期用法是將以下程式碼放入套件的 `__init__.py`：

      from pkgutil import extend_path
      __path__ = extend_path(__path__, __name__)

  For each directory on `sys.path` that has a subdirectory that matches the package name, add the subdirectory to the package's `__path__`. This is useful if one wants to distribute different parts of a single logical package as multiple directories.

  它還會尋找 `*.pkg` 檔案，其中開頭的 `*` 與 name 引數相符。此功能類似於 `*.pth` 檔案（更多資訊請參閱 `site` 模組），但他不特別處理以 `import` 為開頭的行。`*.pkg` 檔案從表面上看是受信任的：除了跳過空行和備註之外，在 `*.pkg` 檔案中找到的所有條目都將新增到路徑中，無論它們是否存在於檔案系統。（這是一個功能。）

  如果輸入路徑不是串列（像是凍結套件 (frozen package) 的情況），它將原封不動地被回傳。輸入路徑不會被修改；而是回傳擴充後的副本。僅將項目附加到副本的尾端。

  `sys.path` 被假設是一個序列，`sys.path` 中的項目裡，若不是代表現存目錄的字串則將被忽略。`sys.path` 上用作檔案名稱時導致錯誤的 Unicode 項目可能會導致此函式引發例外（與 `os.path.isdir()` 行為一致）。

pkgutil.find_loader(fullname)

  取得給定之 fullname 的模組 loader。

  這是一個 `importlib.util.find_spec()` 的向後相容包裝器，它將大多數的失敗轉換為 `ImportError` 並且僅回傳載入器而不是完整的 `importlib.machinery.ModuleSpec`。

  在 3.3 版的變更: 更新為直接基於 `importlib`，而不是依賴套件內部 PEP 302 的引入模擬 (import emulation)。

  在 3.4 版的變更: 基於 PEP 451 來更新

  Deprecated since version 3.12, will be removed in version 3.14: 改用 `importlib.util.find_spec()`。

pkgutil.get_importer(path_item)

  取得給定之 path_item 的 finder。

  如果回傳的尋檢器 (finder) 是由路徑勾點 (path hook) 所新建立的，則它會被快取在 `sys.path_importer_cache` 中。

  如果需要重新掃描 `sys.path_hooks`，可以手動清除快取（或部分快取）。

  在 3.3 版的變更: 更新為直接基於 `importlib`，而不是依賴套件內部 PEP 302 的引入模擬 (import emulation)。

pkgutil.get_loader(module_or_name)

  取得 module_or_name 的 loader 物件。

  如果可以透過正常引入機制存取模組或套件，則回傳該機制相關部分的包裝器。如果找不到或無法引入模組，則回傳 `None`。如果指定的模組尚未被引入，則引入其包含的套件（如有存在）以建立套件 `__path__`。

  在 3.3 版的變更: 更新為直接基於 `importlib`，而不是依賴套件內部 PEP 302 的引入模擬 (import emulation)。

  在 3.4 版的變更: 基於 PEP 451 來更新

  Deprecated since version 3.12, will be removed in version 3.14: 改用 `importlib.util.find_spec()`。

pkgutil.iter_importers(fullname='')

  yield 給定模組名稱的 finder 物件。

  如果 fullname 包含 `'.'`，則尋檢器將針對包含 fullname 的套件，否則它們全部會是在頂層被註冊的尋檢器（即 `sys.meta_path` 和 `sys.path_hooks` 上的尋檢器）。

  如果指定的模組位於套件中，則作為呼叫此函式的副作用 (side effect) ，該套件會被引入。

  如果未指定模組名稱，則會產生所有頂層尋檢器。

  在 3.3 版的變更: 更新為直接基於 `importlib`，而不是依賴套件內部 PEP 302 的引入模擬 (import emulation)。

pkgutil.iter_modules(path=None, prefix='')

  yield path 上所有子模組的 `ModuleInfo`，或者如果 path 為 `None`，則產生 `sys.path` 上的所有頂層模組。

  path 應該是 `None` 或用來尋找模組的路徑串列。

  prefix 是在輸出的每個模組名稱前面的輸出字串。

  備註

  僅適用於有定義 `iter_modules()` 方法的 finder。此介面並非是標準的，因此該模組還提供了 `importlib.machinery.FileFinder` 和 `zipimport.zipimporter` 的實作。

  在 3.3 版的變更: 更新為直接基於 `importlib`，而不是依賴套件內部 PEP 302 的引入模擬 (import emulation)。

pkgutil.walk_packages(path=None, prefix='', onerror=None)

  為 path 上的所有模組遞迴 yield 出 `ModuleInfo`，或如果 path 為 `None` 則 yield 所有可存取的模組。

  path 應該是 `None` 或用來尋找模組的路徑串列。

  prefix 是在輸出的每個模組名稱前面的輸出字串。

  請注意，此函式必須引入給定之 path 上的所有套件（不是所有模組！），以便存取 `__path__` 屬性來尋找子模組。

  onerror 是一個函式，如果在嘗試引入套件時發生任何例外，則使用一個引數（正在引入之套件的名稱）來呼叫函式。如果未提供 onerror 函式，則會捕獲並忽略 `ImportError`，同時傳播所有其他例外並終止搜尋。

  範例：

      # list all modules python can access
      walk_packages()

      # list all submodules of ctypes
      walk_packages(ctypes.__path__, ctypes.__name__ + '.')

  備註

  僅適用於有定義 `iter_modules()` 方法的 finder。此介面並非是標準的，因此該模組還提供了 `importlib.machinery.FileFinder` 和 `zipimport.zipimporter` 的實作。

  在 3.3 版的變更: 更新為直接基於 `importlib`，而不是依賴套件內部 PEP 302 的引入模擬 (import emulation)。

pkgutil.get_data(package, resource)

  從套件中取得資源。

  這是 loader `get_data` API 的包裝器。package 引數應該是採用標準模組格式 (`foo.bar`) 的套件名稱。resource 引數應為相對檔案名稱的形式，並使用 `/` 作為路徑分隔符號。不允許使用父目錄名稱 `..`，也不允許使用根目錄名稱（以 `/` 開頭）。

  該函式回傳一個二進位字串，它是指定資源的內容。

  對於位於檔案系統中且已被引入過的套件，這大致相當於：

      d = os.path.dirname(sys.modules[package].__file__)
      data = open(os.path.join(d, resource), 'rb').read()

  如果無法定位或載入套件，或者它使用不支援 `get_data` 的 loader 則回傳 `None`。特別是命名空間套件的 loader 不支援 `get_data`。

pkgutil.resolve_name(name)

  將名稱解析為物件。

  標準函式庫中的許多地方都使用了此功能（請參閱 bpo-12915），且相同功能也被用於擁有廣大使用者的第三方套件，如 setuptools、Django 和 Pyramid。

  name 預期要是以下格式之一的字串，其中 W 是有效 Python 識別字的簡寫，而點 (dot) 代表這些偽正規表示式 (pseudo-regex) 中的字面句點 (literal period)：

  - `W(.W)*`

  - `W(.W)*:(W(.W)*)?`

  第一種形式僅是為了要向後相容。它假設點名稱 (dotted name) 的某些部分是一個套件，其餘部分是該套件內某處的物件，其可能巢狀地存在於 (nested) 其他物件內。由於無法透過檢查 (inspection) 來推斷出套件停止的位置和物件層次結構的開始位置，因此必須使用此形式來重複嘗試引入。

  在第二種形式中，呼叫者透過使用一個冒號來明確標明分隔點：冒號左側的點名稱是要引入的套件，右側的點名稱是該套件內的物件層次結構。這種形式只需要一次引入。如果它以冒號結尾，則回傳一個模組物件。

  此函式會回傳一個物件（可能是一個模組），或引發以下其中一個例外：

  `ValueError` -- 如果 name 不是可辨識的格式。

  `ImportError` -- 如果在不應該失敗的情況下引入失敗。

  `AttributeError` -- 如果在遍歷引入套件中的物件層次結構以取得所需物件時發生失敗。

  在 3.9 版被加入.