Python - загрузить объект ZipFile в памяти в виде байтов

У меня есть скрипт, который создает закрытый объект ZipFile в памяти, который мне нужно опубликовать в виде строки байтов (используя запросы); как я это сделал? Я попытался открыть файл, который не работает с "TypeError: ожидаемая строка, байты или объект os.PathLike, а не ZipFile"

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

import io
import zipfile
from PIL import Image

z = io.BytesIO()
zfile = zipfile.ZipFile(z,"a")

zipdict = {}

img_loc = "D:/Images/seasons-3.jpg"
im_original = Image.open(img_loc)
imfmt = im_original.format
im = im_original.copy()
im_original.close()
im_out = io.BytesIO()
im.save(im_out,imfmt)
zfile.writestr("seasons-3.jpg",im_out.getvalue())
im_out.close()
zipdict['seasons-3']=zfile
zfile.close()

работает с ошибкой:

Python 3.6.3 (v3.6.3:2c5fed8, Oct  3 2017, 18:11:49) [MSC v.1900 64 bit (AMD64)] on win32
Type "copyright", "credits" or "license()" for more information.
>>> 
>>> zipdict['seasons-3']
<zipfile.ZipFile [closed]>
>>> pl_data = open(zipdict['seasons-3'])
Traceback (most recent call last):
  File "<pyshell#1>", line 1, in <module>
    pl_data = open(zipdict['seasons-3'])
TypeError: expected str, bytes or os.PathLike object, not ZipFile
>>> 

person Tim Achee    schedule 20.11.2018    source источник
comment
Можете ли вы вставить свой код и трассировку ошибок?   -  person Cheche    schedule 20.11.2018
comment
закрытый ZipFile в памяти - вам придется объяснить это еще немного. Вы обернули ZipFile вокруг BytesIO или что-то в этом роде?   -  person user2357112 supports Monica    schedule 20.11.2018
comment
Я не уверен, поможет ли это с zip-файлом в памяти (никогда не сталкивался с таким в дикой природе), но вы можете распаковать один файл из архива: stackoverflow.com/a/46423414/962190   -  person Arne    schedule 20.11.2018
comment
@user2357112 user2357112 именно это я и сделал. Я создал ZipFile и использовал writestr, чтобы добавить пару BytesIO в ZipFile. Затем я добавил ZipFile в качестве значения в словарь с ключом в качестве имени файла и закрыл ZipFile.   -  person Tim Achee    schedule 21.11.2018
comment
@TimAchee: Нет, это все еще ничего не объясняет. Что вы сделали, чтобы поместить ZipFile в память? Какие аргументы вы передали конструктору ZipFile?   -  person user2357112 supports Monica    schedule 21.11.2018
comment
@user2357112 user2357112 Я добавил ZipFile в словарь, чтобы сохранить его в памяти, и передал имя файла и данные в качестве аргументов.   -  person Tim Achee    schedule 21.11.2018
comment
@Cheche извините за это, потребовалось немного времени, чтобы удалить ненужный код. Я только что отредактировал сообщение с кодом и ошибкой.   -  person Tim Achee    schedule 21.11.2018
comment
@Arne Спасибо, Арне, но у меня нет проблем с извлечением содержимого из zip, мне нужно превратить весь zip в поток байтов.   -  person Tim Achee    schedule 21.11.2018
comment
Я добавил ZipFile в диктофон, чтобы сохранить его в памяти - это не то, как работают файлы в памяти. Этот шаг не является необходимым.   -  person user2357112 supports Monica    schedule 21.11.2018


Ответы (1)


zfile закрыто. Это бесполезно для вас. Теперь вам нужно использовать z, файлоподобный объект, который управлял базовым двоичным хранилищем для ZipFile.

Вы можете использовать z.getvalue(), чтобы получить строку байтов, представляющую содержимое z, точно так же, как вы сделали с im_out, или вы можете вернуться к началу с помощью z.seek(0) и использовать его с частями requests, которые принимают файловые объекты.

person user2357112 supports Monica    schedule 21.11.2018
comment
спасибо, user2357112, но мне нужно опубликовать данные в виде строки байтов заархивированного файла, поэтому я не уверен, что это решение сработает. - person Tim Achee; 21.11.2018
comment
@TimAchee: Почему вы думаете, что это не сработает? Похоже, вы неправильно понимаете роль объекта ZipFile. - person user2357112 supports Monica; 21.11.2018
comment
еще раз спасибо и извините за задержку с ответом. Вчера утром я угадал сам и пришел примерно к такому же выводу. Поэтому я попытался загрузить z.getvalue() в качестве своих данных. Пока файл загружен на сервер, система, которую я пытался загрузить, отклонила его с ошибкой (архив не является ZIP-архивом) при распаковке файла. - person Tim Achee; 22.11.2018
comment
@TimAchee: может быть проблема в том, как вы взаимодействуете с веб-API, или, возможно, вы случайно поместили в z что-то еще, кроме содержимого zip. Отсюда трудно сказать. - person user2357112 supports Monica; 22.11.2018
comment
да, когда я запускаю скрипт, сохраняя zip на диск и используя open(path_to_saved_zip) вместо z.getvalue(), все работает. Если я вас правильно понял, z.getvalue() должен быть эквивалентен open(saved_zip), верно? - person Tim Achee; 22.11.2018
comment
@TimAchee: это должно быть больше похоже на open(saved_zip, 'rb').read(), где open — это встроенный open. - person user2357112 supports Monica; 22.11.2018
comment
ах, и это руб. Я думаю, мне нужно найти эквивалент open(saved_zip) без фактического сохраненного zip. - person Tim Achee; 23.11.2018
comment
@TimAchee: z.seek(0) и используйте z. - person user2357112 supports Monica; 23.11.2018
comment
Большое спасибо за то, что остаетесь со мной так далеко. Даже после использования метода seek(0) для z, загрузка z в качестве моих данных по-прежнему вызывает ошибку процесса загрузки с ошибкой (архив не является ZIP-архивом) при распаковке файла. - person Tim Achee; 23.11.2018