Как получить полный путь к файлу ресурса из скрипта Python? - PullRequest
1 голос
/ 01 октября 2019

Хорошо, поэтому я сделал скрипт на языке Python внутри пакета. Дерево выглядит примерно так:

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

Итак, внутри файла сценария я использую cv2 openCV для обнаружения лиц, и для этого cv2.CascadeClassifier требуется путь к файлу XML, расположенному в / resources. Теперь, поскольку это скрипт, мне нужно иметь возможность запускать его из любого места, поэтому относительный путь к файлу ресурса, к сожалению, не помогает. Как я могу получить абсолютный путь к XML-файлу в файле script.py? Вы можете предположить, что скрипт и xml-файл расположены относительно друг друга соответственно, как в примере выше. Спасибо:))

PS: Бонус, если решение работает и с яйцами. Высоко ценится

Ответы [ 3 ]

0 голосов
/ 02 октября 2019

Использование модуля 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)

Это намного более элегантно и должно быть предпочтительным решением, если оно доступно.

0 голосов
/ 09 октября 2019

В настоящее время лучший способ сделать это - 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 каталог.

0 голосов
/ 01 октября 2019

Я не уверен, что правильно понял вопрос, но, может быть, os.path поможет? Что-то вроде:

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