Python: открыть zip-файл из двоичного файла вместо имени файла

Есть ли способ инициализировать ZipFile объект, передавая буквальные байты zip-файла, вместо того, чтобы он прочитал имя файла? Я создаю спокойное приложение, которому не нужно прикасаться к диску; он просто открывает файл, работает с ним, переархивирует и отправляет его дальше.

3 ответа

Решение

В комментариях к другим ответам вы говорите, что хотите сделать это:

открыть двоичную строку, как если бы это был ZIP-файл. Откройте его, прочитайте / запишите файлы внутри него, а затем закройте его

Вы просто делаете то же самое, что и в других ответах, за исключением того, что вы создаете StringIO.StringIO (или же cStringIO.StringIO или же io.BytesIO), который предварительно заполнен двоичной строкой, и извлеките строку в конце. StringIO и друзья принимают необязательную начальную строку для своего конструктора, и имеют getvalue метод для извлечения строки, когда вы закончите. Документация очень проста, и ее стоит прочитать.

Итак, придерживаясь как можно ближе к ответу Алекса:

from zipfile import ZipFile
try:
    import cStringIO as StringIO
except ImportError:
    import StringIO

in_memory = StringIO.StringIO(original_zip_data)
zf = ZipFile(in_memory, "a")  

zf.writestr("file.txt", "some text contents")

zf.close()

new_zip_data = in_memory.getvalue()

Тем не менее, обратите внимание, что ZipFile на самом деле не может писать в zip-архив на месте, за исключением особого случая добавления в него новых файлов. Это так же верно для zip-архивов в памяти, как и на диске. Вы часто можете избежать перезаписи файла в архиве, добавляя новый файл с тем же путем, но обычно это плохая идея (особенно если вы создаете эти вещи для отправки через Интернет).

Итак, то, что вы, вероятно, захотите сделать, точно так же, как и в случае, когда вы хотите изменить файл: создайте отдельный выходной файл, скопируйте необходимые вам данные из входного файла и напишите новые, по мере продвижения. Просто в этом случае входные и выходные файлы ZipFile упаковка объектов StringIO объекты.

Конечно, вместо этого используйте (c)StringIO: http://docs.python.org/2/library/stringio.html Кроме того, вы должны использовать BytesIO для Python 3. Хотя он существует для 2.6 и 2.7.

Вот пример использования (c)StringIO:

from zipfile import ZipFile
try:
    import cStringIO as StringIO
except ImportError:
    import StringIO

in_memory = StringIO.StringIO()   
zf = ZipFile(in_memory, "a")  

zf.writestr("file.txt", "some text contents")

zf.close()

Также см:

Другие вопросы по тегам