Доступ к файлу из яйца питона


Привет, я работаю с упаковкой python. У меня есть 3 non-code файла, а именно ['synonyms.csv', 'acronyms.csv', 'words.txt'].

  • Эти файлы существуют в структуре папок Wordproject/WordProject/Repository/DataBank/
  • у меня есть класс RepositoryReader на пути Wordproject/WordProject/Repository/
  • я написал код, который извлекает текущее местоположение RepositoryReader , а затем ищет subdirectory под названием DataBank и ищет там 3 файла.

Проблема заключается в том, что я создаю egg из кода, а затем запускаю его,

Мой код выдает ошибку:

Не удалось найти файл по адресу X:1. ПроектыпитонаWordprojectvenvЛибсайт-пакетыWordproject-1.0-py3.6.яйцоWordprojectрепозиторийБанк данных синонимы.csv

Он не может извлечь файл или прочитать его из пути, если путь состоит из яйца. Есть ли какой-нибудь способ обойти это? Эти файлы должны быть в egg.

3 2

3 ответа:

Есть две разные вещи, которые вы могли бы попытаться сделать здесь:

  • обрабатывайте файлы данных как часть вашего пакета, как модули Python, и обращайтесь к ним во время выполнения, как если бы ваш пакет был обычным деревом каталогов, даже если это не так.
  • установите файлы данных где-нибудь в другом месте в pip install Время, в месте, к которому вы можете получить обычный доступ.

Оба объяснены вразделе о файлах данных в документах PyPA/setuptools. Я думаю, тебе нужен первый. здесь, который рассматривается в подразделе о доступе к файлам данных во время выполнения :

Как правило, существующие программы манипулируют атрибутом пакета __file__, чтобы найти расположение файлов данных. Однако эта манипуляция несовместима с крючками импорта на основе PEP 302, включая импорт из zip-файлов и яиц Python. Настоятельно рекомендуется, если вы используете файлы данных, использовать ResourceManager API из pkg_resources для доступа к ним. То Модуль pkg_resources распространяется как часть setuptools, поэтому, если вы используете setuptools для распространения вашего пакета, нет причин не использовать его API управления ресурсами. Смотрите также доступ к ресурсам пакета для быстрого примера преобразования кода, который использует __file__ для использования pkg_resources вместо этого.

Перейдите по этой ссылке, и вы найдете то, что выглядит как некоторые crufty old PEAK docs, но это только потому, что они действительно crufty old PEAK docs. Существует версия , похороненная внутри setuptools docs чтобы вам было легче читать и ориентироваться, как только вам это удастся.

Как говорится, вы могли бы try используя get_data (который будет работать внутри яйца/zip), а затем вернуться к доступу к файлу (который будет работать при запуске из исходного кода), но вам лучше использовать обертки в pkg_resources. В принципе, если ваш код делал это:

path = os.path.join(__file__, 'Wordproject/WordProject/Repository/DataBank/', datathingy)
with open(path) as f:
    for line in f:
        do_stuff(line)

... вы измените его на это:

path = 'Wordproject/WordProject/Repository/DataBank/' + datathingy
f = pkg_resources.resource_stream(__name__, path)
for line in f:
    do_stuff(line.decode())
Обратите внимание, что файлы resource_stream всегда открываются в двоичном режиме. Так что если ты хочешь ... прочтите их как текст, вам нужно обернуть вокруг них TextIOWrapper или расшифровать каждую строку.

egg файлы просто переименовываются .сжатый файл.

Вы можете использовать zipfile библиотека, чтобы открыть яйцо и извлечь или прочитать файл, который вам нужен.

import zipfile

zip = zipfile.ZipFile('/path/to/file.egg', 'r')

# open file from within the egg
f = zip.open('synonyms.csv', 'r')
txt = f.read()

Основываясь на документации , мы можем читать содержимое файла несколькими способами.

Решение 1: считайте содержимое файла непосредственно в память.

Без извлечения файла локально.

import zipfile, tempfile
tfile = tempfile.NamedTemporaryFile()
with zipfile.ZipFile('/path/to/egg.egg') as myzip:
    with myzip.open('relative/path/to/file.txt') as myfile:
        tfile.write(myfile.read())

# .. do something with temporary file

tfile.close()

Теперь tfile - это ваш локальный временный дескриптор файла. Это имя tfile.name и все файловые операции, такие как open(tfile) и т. д. работайте над этим, как обычно. tfile.close() должен быть вызван в конце, чтобы закрыть дескриптор.

Содержимое файла может быть прочитано самим myfile.read() но мы теряем дескриптор myfile, как только выходим из контекста. Таким образом, содержимое файла копируется во временный файл, если он должен быть передан для других операций.

Решение 2: извлечь член яйца локально

Zipfile предоставляет API для извлечения конкретного члена

import zipfile
x = zipfile.ZipFile('/path/to/egg.egg')
x.extractall(path='temp/dest/folder', members=['path/to/file.txt'])

Решение 3: извлечь целое яйцо

Другое решение-извлечь яйцо во временную папку, а затем прочитать файл. Яйцо можно извлечь на командная строка выглядит следующим образом
python -m zipfile -e path/to/my.egg ./temp_destination