"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__)

   對於 "sys.path" 上具有與套件名稱相符的子目錄的每個目錄，將該子目錄
   新增至套件的 "__path__" 中。如果想要將單一邏輯套件的不同部分給分配
   到多個目錄時，這會非常有用。

   它還會尋找 "*.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 版被加入.
