Данные доступа Python в подкаталоге Package

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

Я пробовал различные методы, но до сих пор мне не повезло. Похоже, что большинство команд "текущего каталога" возвращают каталог системного интерпретатора python, а не каталог модуля.

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

Любые предложения?

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

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

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

Спасибо!

Ответ 1

Для получения пути к пакету можно использовать символ подчеркивания-underscore-file-underscore-underscore (__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()

Ответ 2

Стандартный способ сделать это - с пакетами 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')

Ответ 3

Предоставить решение, работающее сегодня. Определенно используйте этот 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

Ответ 4

Думаю, я преследовал ответ.

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

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

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

open(os.path.join(data_path,'filename'), <param>)

Ответ 5

Вам нужно имя для всего вашего модуля, вам предоставлено дерево каталогов, не перечисляющее эту деталь, для меня это сработало:

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

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