"importlib.resources" -- 包资源的读取、打开和访问
*************************************************

**源代码:** Lib/importlib/resources/__init__.py

======================================================================

在 3.7 版本加入.

此模块调整了 Python 的导入系统以便提供对 *包* 内部的 *资源* 的访问。

“资源”是指 Python 中与模块或包相关联的文件类资源。 资源可以直接包含在
某个包中，包含在某个包的子目录中，或是与某个包外部的模块相邻。 资源可
以是文本或二进制数据。 因此，从技术上说 Python 包的模块源代码文件
(.py) 和编译结果文件 (pycache) 就是包实际所包含的资源。 但是，在实践中
，资源主要是指包作者专门公开的非 Python 文件。

资源可以使用二进制或文本模式打开。

资源大致相当于目录内的文件，不过需要记住这只是一个比喻。 资源和包 **不
是** 必须如文件系统上的物理文件和目录那样存在的：例如，一个包及其资源
可使用 "zipimport" 从一个 ZIP 文件导入。

备注:

  本模块提供了类似于 pkg_resources Basic Resource Access 的功能而没有
  那样高的性能开销。 这使得读取包中的资源更为容易，并具有更为稳定和一
  致的语义。此模块的独立向下移植版本在 using importlib.resources 和
  migrating from pkg_resources to importlib.resources 中提供了更多信息
  。

想要支持资源读取的 "加载器" 应当实现
"importlib.resources.abc.ResourceReader" 中规定的
"get_resource_reader(fullname)" 方法。

class importlib.resources.Anchor

   代表资源的锚点，可以是一个 "模块对象" 或字符串形式的模块名称不。 定
   义为 "Union[str, ModuleType]"。

importlib.resources.files(anchor: Anchor | None = None)

   返回一个代表资源容器（相当于目录）及其资源（相当于文件）的
   "Traversable" 对象。 Traversable 可以包含其他容器（相当于子目录）。

   *anchor* 是一个可选的 "Anchor"。 如果 anchor 是一个包，则会从这个包
   获取资源。 如果是一个模块，则会从这个模块的相邻位置获取资源（在同一
   个包或包的根目录中）。 如果省略了 anchor,则会使用调用方的模块。

   在 3.9 版本加入.

   在 3.12 版本发生变更: *package* 形参被重命名为 *anchor*。 *anchor*
   现在可以是一个不为包的模块，如果被省略则默认为调用方的模块。 为保持
   兼容性 *package* 仍然被接受但会引发 "DeprecationWarning"。 请考虑以
   位置参数方式传入或使用 "importlib_resources >= 5.10" 作为针对旧版
   Python 的兼容接口。

importlib.resources.as_file(traversable)

   给定一个代表文件或目录的 "Traversable" 对象，通常是来自
   "importlib.resources.files()"，返回一个上下文管理器以供 "with" 语句
   使用。 该上下文管理器提供一个 "pathlib.Path" 对象。

   退出上下文管理器后会清除从 zip 文件等提取资源时创建的任何临时文件或
   目录。

   当 Traversable 的方法（如 "read_text" 等）不足以满足需要而需要文件
   系统中的真实文件或目录时请使用 "as_file"。

   在 3.9 版本加入.

   在 3.12 版本发生变更: 增加了对代表目录的 *traversable* 的支持。


弃用的函数
==========

一组旧式的，已被弃用的函数仍然可用，但预计会在未来的 Python 版本中被移
除。 这些函数的主要缺点是它们不支持目录：它们假定所有资源都直接位于
*package* 之下。

importlib.resources.Package

      只要一个函数接受 "Package" 参数，你就可以传入 "模块对象" 或字符
      串形式的模块名称。 你只能传入
      "__spec__.submodule_search_locations" 不为 "None" 的模块对象。

      "Package" 类型是作为 "Union[str, ModuleType]" 定义的。

   自 3.12 版本弃用.

importlib.resources.Resource

   对于下列函数的 *resource* 参数，你可以传入字符串形式的资源名称或 "
   路径类对象"。

   "Resource" 类型是作为 "Union[str, os.PathLike]" 定义的。

importlib.resources.open_binary(package, resource)

   以二进制读方式打开 *package* 内的 *resource*。

   *package* 是包名或符合 "Package" 要求的模块对象。 *resource* 是要在
   *package* 内打开的资源名；不能包含路径分隔符，也不能有子资源（即不
   能为目录）。本函数将返回一个 "typing.BinaryIO" 实例以供读取，即一个
   已打开的二进制 I/O 流。

   自 3.11 版本弃用: 对此函数的调用可以被替换为:

      files(package).joinpath(resource).open('rb')

importlib.resources.open_text(package, resource, encoding='utf-8', errors='strict')

   以文本读方式打开 *package* 内的 *resource*。默认情况下，资源将以
   UTF-8 格式打开以供读取。

   *package* 是包名或符合 "Package" 要求的模块对象。 *resource* 是要在
   *package* 内打开的资源名；不能包含路径分隔符，也不能有子资源（即不
   能是目录）。*encoding* 和 *errors* 的含义与内置 "open()" 的一样。

   本函数返回一个 "typing.TextIO" 实例，即一个打开的文本 I/O  流对象以
   供读取。

   自 3.11 版本弃用: 对此函数的调用可以被替换为:

      files(package).joinpath(resource).open('r', encoding=encoding)

importlib.resources.read_binary(package, resource)

   读取并返回 *package* 中的 *resource* 内容，格式为 "bytes"。

   *package* 是包名或符合 "Package" 要求的模块对象。 *resource* 是要在
   *package* 内打开的资源名；不能包含路径分隔符，也不能有子资源（即不
   能是目录）。资源内容以 "bytes" 的形式返回。

   自 3.11 版本弃用: 对此函数的调用可以被替换为:

      files(package).joinpath(resource).read_bytes()

importlib.resources.read_text(package, resource, encoding='utf-8', errors='strict')

   读取并返回 *package* 中 *resource* 的内容，格式为 "str"。默认情况下
   ，资源内容将以严格的 UTF-8 格式读取。

   *package* 是包名或符合 "Package" 要求的模块对象。 *resource* 是要在
   *package* 内打开的资源名；不能包含路径分隔符，也不能有子资源（即不
   能是目录）。*encoding* 和 *errors* 的含义与内置 "open()" 的一样。资
   源内容将以 "str" 的形式返回。

   自 3.11 版本弃用: 对此函数的调用可以被替换为:

      files(package).joinpath(resource).read_text(encoding=encoding)

importlib.resources.path(package, resource)

   返回 *resource* 实际的文件系统路径。本函数返回一个上下文管理器，以
   供 "with" 语句中使用。上下文管理器提供一个 "pathlib.Path" 对象。

   退出上下文管理程序时，可以清理所有临时文件，比如从压缩文件中提取资
   源时创建的那些文件。

   *package* 是包名或符合 "Package" 要求的模块对象。 *resource* 是要在
   *package* 内打开的资源名；不能包含路径分隔符，也不能有子资源（即不
   能是目录）。

   自 3.11 版本弃用: 对此函数的调用可以使用 "as_file()" 来替换:

      as_file(files(package).joinpath(resource))

importlib.resources.is_resource(package, name)

   如果包中存在名为 *name* 的资源则返回 "True"，否则返回 "False"。 此
   函数不会将目录视为资源。 *package* 是包名或符合 "Package" 要求的模
   块对象。

   自 3.11 版本弃用: 对此函数的调用可以被替换为:

      files(package).joinpath(resource).is_file()

importlib.resources.contents(package)

   返回一个用于遍历包内各命名项的可迭代对象。该可迭代对象将返回 "str"
   资源（如文件）及非资源（如目录）。该迭代器不会递归进入子目录。

   *package* 是包名或符合 "Package" 要求的模块对象。

   自 3.11 版本弃用: 对此函数的调用可以被替换为:

      (resource.name for resource in files(package).iterdir() if resource.is_file())
