Данные доступа к Python в подкаталоге пакета - PullRequest
98 голосов
/ 23 апреля 2009

Я пишу пакет python с модулями, которые должны открывать файлы данных в подкаталоге ./data/. Прямо сейчас у меня есть пути к файлам, жестко закодированным в мои классы и функции. Я хотел бы написать более надежный код, который может получить доступ к подкаталогу независимо от того, где он установлен в системе пользователя.

Я пробовал разные методы, но пока мне не повезло. Кажется, что большинство команд «current directory» возвращают каталог системного интерпретатора python, а не каталог модуля.

Кажется, это должно быть тривиальной общей проблемой. Тем не менее, я не могу понять это. Частично проблема заключается в том, что мои файлы данных не являются файлами .py, поэтому я не могу использовать функции импорта и тому подобное.

Есть предложения?

Прямо сейчас мой каталог пакетов выглядит так:

/
__init__.py
module1.py
module2.py
data/   
   data.txt

Я пытаюсь получить доступ к data.txt с module*.py

Спасибо!

Ответы [ 5 ]

138 голосов
/ 09 апреля 2011

Стандартный способ сделать это с помощью пакетов setuptools и pkg_resources.

Вы можете расположить свой пакет в соответствии со следующей иерархией и настроить файл установки пакета так, чтобы он указывал на ваши ресурсы данных по этой ссылке:

http://docs.python.org/distutils/setupscript.html#installing-package-data

Затем вы можете повторно найти и использовать эти файлы, используя pkg_resources, по этой ссылке:

http://peak.telecommunity.com/DevCenter/PkgResources#basic-resource-access

import pkg_resources

DATA_PATH = pkg_resources.resource_filename('<package name>', 'data/')
DB_FILE = pkg_resources.resource_filename('<package name>', 'data/sqlite.db')
23 голосов
/ 23 апреля 2009

Вы можете использовать __file__, чтобы получить путь к пакету, например:

import os
this_dir, this_filename = os.path.split(__file__)
DATA_PATH = os.path.join(this_dir, "data", "data.txt")
print open(DATA_PATH).read()
12 голосов
/ 09 октября 2014

Чтобы обеспечить решение, работающее сегодня. Обязательно используйте этот API, чтобы не изобретать все эти колеса.

Требуется настоящее имя файла в файловой системе. Молнии яйца будут извлечены в каталог кеша:

from pkg_resources import resource_filename, Requirement

path_to_vik_logo = resource_filename(Requirement.parse("enb.portals"), "enb/portals/reports/VIK_logo.png")

Возвращает читаемый файлоподобный объект для указанного ресурса; это может быть реальный файл, StringIO или какой-либо подобный объект. Поток находится в «двоичном режиме» в том смысле, что все байты в ресурсе будут считываться как есть.

from pkg_resources import resource_stream, Requirement

vik_logo_as_stream = resource_stream(Requirement.parse("enb.portals"), "enb/portals/reports/VIK_logo.png")

Обнаружение пакетов и доступ к ресурсам с использованием pkg_resources

7 голосов
/ 23 апреля 2009

Кажется, я нашел ответ.

Я создаю модуль data_path.py, который импортирую в другие мои модули, содержащий:

data_path = os.path.join(os.path.dirname(__file__),'data')

И затем я открываю все свои файлы с помощью

open(os.path.join(data_path,'filename'), <param>)
6 голосов
/ 10 декабря 2015

Вам нужно имя для всего модуля, вам дано дерево каталогов, в котором нет этой детали, для меня это сработало:

import pkg_resources
print(    
    pkg_resources.resource_filename(__name__, 'data/data.txt')
)

Замечательно, что setuptools не разрешает файлы на основе совпадения имен с файлами упакованных данных, так что вы должны добавить префикс data/ почти независимо от того, что. Вы можете использовать os.path.join('data', 'data.txt), если вам нужны альтернативные разделители каталогов. Обычно я не вижу проблем с совместимостью с жестко закодированными разделителями каталогов в стиле Unix.

...