好的,所以我在包中做了一个python脚本。树看起来像这样:
├── foo
│ ├── __init__.py
│ ├── funcs
│ │ ├── __init__.py
│ │ └── stuff.py
│ ├── resources
│ │ └── haarcascade_frontalface_default.xml
│ └── scripts
│ ├── __init__.py
│ └── script.py
└── setup.py
因此,在脚本文件中,im使用 openCV 的 cv2 来检测人脸,为此cv2.CascadeClassifier
需要位于/resources 下的 XML 文件的路径。现在,由于这是一个脚本,我需要能够从任何地方运行它,因此可悲的是,资源文件的相对路径无法解决问题。如何从 script.py 中获取 xml 文件的绝对路径?您可以假设脚本和 xml 文件分别相对位于彼此的位置,就像上面的示例一样。谢谢:)(
PS:如果解决方案也适用于鸡蛋,则奖金。非常感谢
目前最好的方法是importlib.resources
.从 Python 3.7 开始,它在标准库中可用。对于早期版本,有一个名为importlib_resources
的向后端口。
按照文档进行操作。
在您的情况下,这或多或少应该如下所示:
import importlib.resources
xml_path = importlib.resources.path('foo.resources', 'haarcascade_frontalface_default.xml')
这样做有很多优点,最重要的是它是标准的,即使它在zip文件中安装软件包,它也可以在任何地方工作。
在这种情况下,您可能需要将__init__.py
文件添加到resources
目录中。
使用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)
这要优雅得多,并且应该是首选解决方案,因为它是可用的。
我不确定我是否正确理解了这个问题,但也许os.path
会有所帮助?像这样:
>>> import os
>>> os.path.abspath("directory/somefile.txt")
'C:/somedirectory/directory/directory/somefile.txt'