如何从 python 脚本中获取资源文件的完整路径?

How to get full path of resource file from within python script?

好的,所以我在包中制作了一个 python 脚本。这棵树看起来像这样:

├── foo
│   ├── __init__.py
│   ├── funcs
│   │   ├── __init__.py
│   │   └── stuff.py
│   ├── resources
│   │   └── haarcascade_frontalface_default.xml
│   └── scripts
│       ├── __init__.py
│       └── script.py
└── setup.py

所以在脚本文件中,我使用 openCV 的 cv2 来检测人脸,为此 cv2.CascadeClassifier 需要位于 /resources 下的 XML 文件的路径。现在因为这是一个脚本,我需要能够从任何地方 运行 它,所以很遗憾,资源文件的相对路径并不能解决问题。如何从 script.py 中获取 xml 文件的绝对路径?您可以假设脚本和 xml 文件分别相对于彼此定位,就像上面的示例一样。谢谢:))

PS:如果解决方案也适用于鸡蛋,则奖励。非常感谢

我不确定我是否正确理解了问题,但也许 os.path 会有所帮助?类似于:

>>> import os
>>> os.path.abspath("directory/somefile.txt")
'C:/somedirectory/directory/directory/somefile.txt'

使用 os 模块是可行的,但如果您可以访问 python 版本 >= 3.4,那么 pathlib 是一个更容易处理的替代方案,并且跨平台表现更好:

from pathlib import Path

# when using pathlib.Path, slashes get automatically transformed into the 
# correct path-division character, depending on the platform
RESOURCES_PATH = Path(__file__).parent.parent / "resources"

face_cascade = cv2.CascadeClassifier()
face_cascade.load(RESOURCES_PATH / "haarcascade_frontalface_default.xml")

如果您发现自己定义了很多此类常量,请考虑将它们全部放在一个文件中,例如 foo/util.py,这样它们就可以在您的项目中轻松重用,并且不需要重新声明或从脚本导入。


python 版本 >=3.7 中更好的选择是使用 importlib.resources.path,它会自动从包根目录解析资源,因此您无需手动查找从 __file__ 走上去:

import importlib

face_cascade = cv2.CascadeClassifier()
with importlib.resources.path("foo.resources", "haarcascade_frontalface_default.xml") as haar_resource:
    # haar_resource is a pathlib.Path object here as well, so plugging it is simple
    face_cascade.load(haar_resource)

这更优雅,应该是首选解决方案,因为它可用。

目前最好的方法是 importlib.resources. Since Python 3.7 it is available in the standard library. For earlier versions, there is a backport called importlib_resources

关注documentation.

在您的情况下,这应该大致如下所示:

import importlib.resources
xml_path = importlib.resources.path('foo.resources', 'haarcascade_frontalface_default.xml')

这有很多优点,最重要的是它是标准的,即使安装在 zip 文件中,它也可以在安装包的任何地方使用。

在您的情况下,您可能 必须将 __init__.py 文件添加到 resources 目录。