如何从 Python 包内部读取(静态)文件?

2023-11-24

你能告诉我如何读取 Python 包中的文件吗?

我的情况

我加载的包有许多我想从程序中加载的模板(用作字符串的文本文件)。但如何指定此类文件的路径呢?

想象一下我想从以下位置读取文件:

package\templates\temp_file

某种路径操纵?包基本路径跟踪?


TLDR;使用标准库importlib.resources module

如果你不关心向后兼容性

from importlib import resources as impresources
from . import templates

inp_file = (impresources.files(templates) / 'temp_file')
with inp_file.open("rt") as f:
    template = f.read()

Details

The 传统的 pkg_resources from setuptools不再推荐,因为新方法:

  • it is 性能显着提高;
  • 这是更安全的,因为使用包(而不是路径字符串)会引发编译时错误;
  • 它更直观,因为您不必“连接”路径;
  • 仅依赖于 Python 的标准库(没有额外的 3rdp 依赖项setuptools).

我保留了传统的首先列出,以解释在移植现有代码时与新方法的差异(也移植)在这里解释).



假设您的模板位于模块包内嵌套的文件夹中:

  <your-package>
    +--<module-asking-the-file>
    +--templates/
          +--temp_file                         <-- We want this file.

Note 1:当然,我们不应该摆弄__file__属性(例如,当从 zip 中提供代码时,代码将会中断)。

Note 2:如果您正在构建此包,请记住将您的数据文件声明为package_data or data_files在你的setup.py.

1)使用pkg_resources from setuptools(slow)

您可以使用pkg_resources包裹来自设置工具分布,但是这是有代价的,性能方面:

import pkg_resources

# Could be any dot-separated package/module name or a "Requirement"
resource_package = __name__
resource_path = '/'.join(('templates', 'temp_file'))  # Do not use os.path.join()
template = pkg_resources.resource_string(resource_package, resource_path)
# or for a file-like stream:
template = pkg_resources.resource_stream(resource_package, resource_path)

Tips:

  • 即使您的发行版被压缩,这也会读取数据,因此您可以设置zip_safe=True在你的setup.py,和/或使用期待已久的zipapp packer from python-3.5创建独立的发行版。

  • 记得添加setuptools进入您的运行时要求(例如在 install_requires` 中)。

...并注意根据Setuptools/pkg_resources文档,你不应该使用os.path.join:

基本资源访问

请注意,资源名称必须是/- 分隔的路径并且不能是绝对的(即没有前导/) 或包含相对名称,例如“..". Do not use os.path按原样操作资源路径的例程not文件系统路径。

2) Python >= 3.7,或使用向后移植的importlib_resources library

使用标准库的importlib.resources module这比更有效setuptools, above:

try:
    from importlib import resources as impresources
except ImportError:
    # Try backported to PY<37 `importlib_resources`.
    import importlib_resources as impresources

from . import templates  # relative-import the *package* containing the templates

try:
    inp_file = (impresources.files(templates) / 'temp_file')
    with inp_file.open("rb") as f:  # or "rt" as text file with universal newlines
        template = f.read()
except AttributeError:
    # Python < PY3.9, fall back to method deprecated in PY3.11.
    template = impresources.read_text(templates, 'temp_file')
    # or for a file-like stream:
    template = impresources.open_text(templates, 'temp_file')

注意力:

关于功能read_text(package, resource):

  • The package可以是字符串或模块。
  • The resource不再是路径,而只是现有包中要打开的资源的文件名;它可能不包含路径分隔符,并且可能没有子资源(即它不能是目录)。

对于问题中提出的示例,我们现在必须:

  • 使<your_package>/templates/通过创建一个空的包到一个正确的包中__init__.py文件在里面,
  • 所以现在我们可以使用一个简单的(可能是相对的)import语句(不再解析包/模块名称),
  • 并简单地要求resource_name = "temp_file"(没有路径)。

Tips:

  • 访问文件在当前模块内,将包参数设置为__package__, e.g. impresources.read_text(__package__, 'temp_file')(感谢@ben-mares)。
  • 当事情变得有趣时实际文件名被问及path(),因为现在上下文管理器用于临时创建的文件(阅读this).
  • 添加向后移植的库,有条件地适用于较旧的 Python,使用install_requires=[" importlib_resources ; python_version<'3.7'"] (check this如果你打包你的项目setuptools<36.2.1).
  • 记得删除setuptools图书馆从你的运行时要求,如果您从传统方法迁移。
  • 记得定制setup.py or MANIFEST to 包含任何静态文件.
  • 您还可以设置zip_safe=True在你的setup.py.
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何从 Python 包内部读取(静态)文件? 的相关文章

随机推荐

  • Ipython、jupyter 和内核之间有什么关系?

    就像每次我寻找有关 python 或 R 的答案时 我都会遇到 Ipython Ipython kernel Ipython Notebook jupyter 和 jupyter kernel 的这些含义 并且我实际上了解每个的用途 但我对
  • 如何修复 Heroku imagecreatefromjpeg()

    heroku 报告我一个错误 Call to undefined function imagecreatefromjpeg at line 177 其中第 177 行是 案例 jpg 案例 jpeg image data imagecrea
  • Python如何获取QLineEdit文本?

    你好世界我正在尝试让 QLineEdit 作为用户输入来工作 他们应该输入歌曲名称 输入歌曲名称后 我希望单击播放按钮后开始播放该歌曲 除了他们可以在该文件夹中输入所需歌曲的部分之外 一切正常 问题是我不确定如何制作 QlineEdit 单
  • 使用指针算术计算类型大小的替代方法

    下面的代码是100 可移植的吗 int a 10 size t size of int char a 1 char a No problem here std cout lt
  • 两个表的索引名称相同

    我正在为我们的团队构建一个小型 Mysql 数据库 对于我的数据库中的两个表 我使用了相同的索引名称 性能会受到影响吗 我做了一些测试查询 800 000 多行 到目前为止 一切顺利 索引名称特定于每个表 一张表中不能有两个同名索引 但可以
  • 如何在 Scala 中定义列表的列表?

    我想为以下类型创建一个存储 List List 2 3 1 1 List 2 2 1 但如果我执行以下操作 var y List List 1 0 2 2 List 2 1 1 2 1 然后它创建为 List AnyVal 并在我尝试执行数
  • Boost Python 中的跨模块依赖

    假设我有两个 boost python 模块 定义如下 模块A class SomeClass public SomeClass SomeClass BOOST PYTHON MODULE A class
  • 如何模拟按下按钮?

    我想测试一些表格 有没有办法模拟按下 确定 或 取消 按钮 以便按下该按钮并触发与其关联的事件处理程序 最简洁的方法是调用按钮的 Click 方法 由于以下原因 这比替代方案更好 您可以读取 OnClick 属性 检查它是否为 nil 然后
  • 编写 Maven 插件/Mojo:如何让一个目标强制执行其他目标?

    注意 此线程是关于编写自定义 Mojo 而不是使用插件 我维持一个测试插件对于马文来说 不幸的是 近一年来 我一直让这种特殊的未知挥之不去 我真的很想知道如何处理它 以便其用户可以拥有更简单的配置 假设我们的插件有两个目标 prepare
  • 应用程序作用域 bean 中的实用方法

    您认为将所有广泛使用的实用程序方法放在应用程序范围的 bean 中是一个好主意吗 在我正在开发的应用程序的当前实现中 所有实用方法 使用字符串 cookie 进行操作 检查 url 检查用户所在的当前页面等 都放在一个大请求作用域 bean
  • NHibernate 如何实现变更跟踪?

    nhibernate 代理是否做了任何聪明的工作来提高更改跟踪的效率 或者它只支持实体框架所谓的基于快照的更改跟踪 它是基于快照的 加载实体时 其状态作为 object 存储在会话中 刷新时 当前状态会转换为 object 并与原始状态进行
  • 在站点根文件夹内的文件夹中定义 HTML 根

    我想要一个包含一组新 html 文件的新文件夹 里面的所有图片都是这样的格式src image png and image png位于根文件夹中 但是当您将 HTML 文件放入新文件夹时 它找不到该图像 您必须采用以下格式src root
  • 从控制器传递图像并使用 ASP.NET MVC 3 中的 ViewBag 在视图中显示

    我想这是非常简单的事情 但我不知道如何去做 在我的控制器中我有 public ViewResult ShowForm ViewBag Title Resources ApplicationTitle ViewBag LabelStatus
  • 在 eventArgs 中发送两个字符串的语法

    在下面的代码中 我需要知道引发事件时传递两个字符串的语法 PublishEvent Click public event EventHandler
  • 如何使用 python numpy.savetxt 将字符串和浮点数写入 ASCII 文件?

    我有一组包含字符串和浮点数的列表 例如 import numpy as num NAMES num array NAME 1 NAME 2 NAME 3 FLOATS num array 0 5 0 2 0 3 DAT num column
  • matplotlib:ValueError:无效的 PNG 标头

    import matplotlib pyplot as plt 我试图在同一文件夹中的许多其他 png 照片中读取一张 png 照片 有些照片使用以下行读取时没有错误 有些则返回 ValueError 无效的 PNG 标头 可能是什么原因
  • 如何使用SQL Order By语句对结果进行不区分大小写的排序?

    我有一个 SQLite 数据库 我试图按字母顺序排序 问题是 SQLite 在排序过程中似乎没有考虑 A a 因此我得到这样的结果 A 乙 C 时间 A 乙 C G 我想得到 A A 乙 乙 C C G 时间 有哪些我不知道的特殊 SQL
  • 如何防止

    在超过页面宽度时被剪裁?

    我正在使用 jQuery Mobile 但我的一个页面出现了问题 我有一个 p 嵌入到列表中 如下所示 p div div h1 Page 1 h1 div div ul li List Heading li li p A very lon
  • 在 Firestore 规则中声明函数

    这是我现在面临的 Firestore 安全规则问题 首先 这是我的 firestore 数据库中的数据结构示例 userProfiles userId userData companies companyId companyData 看起来
  • 如何从 Python 包内部读取(静态)文件?

    你能告诉我如何读取 Python 包中的文件吗 我的情况 我加载的包有许多我想从程序中加载的模板 用作字符串的文本文件 但如何指定此类文件的路径呢 想象一下我想从以下位置读取文件 package templates temp file 某种