如何相对于包目录引用文件?
我的目录结构是:
/foo 套餐1/ 资源/ __init__.py 套餐2/ 资源/ __init__.py 脚本.py
script.py
导入包 package1
和 package2
。尽管这些包可以通过系统上的任何其他脚本导入。我应该如何引用 package1
内部的资源,以确保在 os.path.curdir
任意的情况下它能够工作?
如果您想引用
foo/package1/resources
文件夹中的文件,则需要使用模块的 __file__
变量。里面foo/package1/__init__.py
:
from os import path
resources_dir = path.join(path.dirname(__file__), 'resources')
一个简单/安全的方法是使用
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')
这为您提供了一个干净的解决方案,而且(如果我没记错的话)拉链安全。
如果您使用 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。
使用
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()
这是一个坏主意,因为,如果你的包是作为压缩的egg安装的,那么资源可能不可用。
如果您使用 setuptool,请不要忘记将 zip_safe=False 添加到 setup.py 配置中。