Доступ к файлу из яйца питона
Привет, я работаю с упаковкой 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 ответа:
Есть две разные вещи, которые вы могли бы попытаться сделать здесь:
- обрабатывайте файлы данных как часть вашего пакета, как модули 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