Я пишу пакет python с модулями, которым необходимо открывать файлы данных в ./data/
подкаталоге. Прямо сейчас у меня есть пути к файлам, жестко закодированные в мои классы и функции. Я хотел бы написать более надежный код, который может получить доступ к подкаталогу независимо от того, где он установлен в системе пользователя.
Я пробовал разные методы, но пока безуспешно. Кажется, что большинство команд «текущего каталога» возвращают каталог системного интерпретатора python, а не каталог модуля.
Похоже, это должна быть обычная тривиальная проблема. Но я не могу понять этого. Частично проблема в том, что мои файлы данных не являются .py
файлами, поэтому я не могу использовать функции импорта и тому подобное.
Какие-либо предложения?
Сейчас мой каталог пакетов выглядит так:
/
__init__.py
module1.py
module2.py
data/
data.txt
Я пытаюсь получить доступ data.txt
из module*.py
!
Ответы:
Вы можете использовать,
__file__
чтобы получить путь к пакету, например:источник
__file__
не работает с py2exe, так как значением будет путь к zip-файлу.Стандартный способ сделать это - использовать пакеты setuptools и pkg_resources.
Вы можете разместить свой пакет в соответствии со следующей иерархией и настроить файл установки пакета так, чтобы он указывал на ваши ресурсы данных, согласно этой ссылке:
http://docs.python.org/distutils/setupscript.html#installing-package-data
Затем вы можете повторно найти и использовать эти файлы с помощью pkg_resources по этой ссылке:
http://peak.telecommunity.com/DevCenter/PkgResources#basic-resource-access
источник
python-setuptools
только в этом? Пока__file__
у меня все работает нормально.from pkg_resources import resource_filename open(resource_filename('data', 'data.txt'), 'rb')
importlib.resources
заменяетpkg_resources
для этой цели (из-за проблем с производительностью).Чтобы предоставить решение, работающее сегодня. Определенно используйте этот API, чтобы не изобретать все эти колеса.
Требуется настоящее имя файла файловой системы. Сжатые яйца будут извлечены в каталог кеша:
Вернуть читаемый объект в виде файла для указанного ресурса; это может быть реальный файл, StringIO или другой подобный объект. Поток находится в «двоичном режиме» в том смысле, что любые байты, находящиеся в ресурсе, будут читаться как есть.
Обнаружение пакетов и доступ к ресурсам с помощью pkg_resources
источник
Часто нет смысла давать ответ, в котором подробно описывается код, который не работает как есть, но я считаю, что это исключение. Добавлен Python 3.7,
importlib.resources
который должен заменитьpkg_resources
. Это будет работать для доступа к файлам внутри пакетов, в именах которых нет косой черты , т.е.т.е. вы можете получить доступ к
data2.txt
пакету,foo
например,но он потерпит неудачу за исключением
Это не может быть решена только путем размещения
__init__.py
вdata
и затем использовать его в качестве пакета:Причина такого поведения - «это намеренно» ; но дизайн может измениться ...
источник
"This was a deliberate choice, but I think you have a valid use case. @brettcannon what do you think? And if we allow this, should we make sure it gets into Python 3.7?"
Вам нужно имя для всего вашего модуля, вам дано дерево каталогов, не перечисляющее эту деталь, для меня это сработало:
Notibly setuptools, похоже, не разрешает файлы на основе совпадения имен с файлами упакованных данных, так что вы должны включать
data/
префикс в значительной степени, несмотря ни на что. Вы можете использовать,os.path.join('data', 'data.txt)
если вам нужны альтернативные разделители каталогов. Обычно я не вижу проблем совместимости с жестко запрограммированными разделителями каталогов в стиле unix.источник
Думаю, я нашел ответ.
Я создаю модуль data_path.py, который импортирую в другие мои модули, содержащие:
Затем я открываю все свои файлы с помощью
источник
pkg_resources.resource_string('pkg_name', 'data/file.txt')
__file__
где-то использовали . В моем случае я использую библиотеку, которой действительно нужны пути, а не потоки. Конечно, я мог бы временно записать файлы на диск, но из-за лени я просто использую функцию setuptools.