Python 包中的相对文件路径

问题描述 投票:0回答:5

如何相对于包目录引用文件?

我的目录结构是:

 /foo
     套餐1/
      资源/
      __init__.py
     套餐2/
      资源/
      __init__.py
     脚本.py

script.py
导入包
package1
package2
。尽管这些包可以通过系统上的任何其他脚本导入。我应该如何引用
package1
内部的资源,以确保在
os.path.curdir
任意的情况下它能够工作?

python reference package relative-path
5个回答
27
投票

如果您想引用

foo/package1/resources
文件夹中的文件,则需要使用模块的
__file__
变量。里面
foo/package1/__init__.py

from os import path
resources_dir = path.join(path.dirname(__file__), 'resources')

14
投票

一个简单/安全的方法是使用

pkg_resources
中的 resource_filename 方法(与 setuptools 一起分发),如下所示:

from pkg_resources import resource_filename
filepath = resource_filename('package1', 'resources/thefile')

或者,如果您在内部实现此功能

package1/___init___.py

from pkg_resources import resource_filename
filepath = resource_filename(__name__, 'resources/thefile')

这为您提供了一个干净的解决方案,而且(如果我没记错的话)拉链安全。


4
投票

如果您使用 twisted.python.modules.

,您可以实现 zip 安全,同时使用方便的 API

例如,如果我有一个

data.txt
,其中包含一些文本,并且这个
sample.py
在一个目录中:

from twisted.python.modules import getModule
moduleDirectory = getModule(__name__).filePath.parent()
print repr(moduleDirectory.child("data.txt").open().read())

然后导入

sample
将执行此操作:

>>> import sample
'Hello, data!\n'
>>>

如果您的模块位于常规目录中,则

getModule(__name__).filePath
将是FilePath;如果它在 zip 文件中,它将是一个 ZipPath,它支持大多数(但不是全部)相同的 API。


0
投票

使用

importlib_resources

添加到问题中的示例中,您可能会得到如下所示的内容:

 /foo
     套餐1/
      资源/
      __init__.py
      资源1.txt
     套餐2/
      资源/
      __init__.py
     脚本.py

在Python中你可以使用:

from importlib_resources import files
resource_path = files('package1.resources').joinpath('resource1.txt')
resource_contents = resource_path.read_text()

-1
投票

这是一个坏主意,因为,如果你的包是作为压缩的egg安装的,那么资源可能不可用。

如果您使用 setuptool,请不要忘记将 zip_safe=False 添加到 setup.py 配置中。

© www.soinside.com 2019 - 2024. All rights reserved.