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