Python包中的相对文件路径

20

如何相对引用一个包(package)的目录下的文件?

我的目录结构如下:

    /foo
     package1/
      resources/
      __init__.py
     package2/
      resources/
      __init__.py
     script.py

script.py 导入了 package1package2 包,尽管其他系统中的脚本也可以导入这些包。如果我想引用例如 package1 中的资源(resources),应该如何确保在 os.path.curdir 是任意值的情况下也能正常工作呢?

4个回答

25

如果你想从foo/package1/resources文件夹引用文件,你需要使用模块的__file__变量。在foo/package1/__init__.py中:

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

正如另一个答案所指出的那样,如果您的应用程序被打包在zip文件中,这种方法将无法工作。 - Glyph

14

一个简单/安全的方法是使用 pkg_resources 中的 resource_filename 方法(与 setuptools 一起分发),如下所示:

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

或者,如果您正在 package1/___init___.py 中实现此操作:

Translated:

或者,如果您在package1/___init___.py中实施此操作:

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

这为你提供了一个干净的解决方案,同时也是(如果我没有错的话)zip安全的。


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。

-1

这是一个糟糕的想法,因为如果您的软件包被安装为压缩的egg文件,那么资源可能不可用。

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


6
没错,但这更适合作为评论而不是答案,因为它并没有回答问题。 - Glyph

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接