Есть ли способ инициализировать объект ZipFile
, передав буквальные байты zip-файла вместо того, чтобы читать имя файла? Я создаю спокойное приложение, которому не нужно прикасаться к диску; он просто открывает файл, что-то с ним делает, повторно архивирует и отправляет.
Python: открыть 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
:
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()
Также см:
- https://stackoverflow.com/questions/2411514/function-to-create-in-memory-zip-file-and-return-as-http-response
- Как я могу передать объект Python StringIO() в ZipFile(), или он не поддерживается?
- Zip-файлы Django (создавайте динамические архивы в памяти с помощью zip-файла Python)
Конечно, вместо этого используйте (c)StringIO: http://docs.python.org/2/library/stringio.html Кроме того, вам следует использовать BytesIO для Python 3. Однако он существует для версий 2.6 и 2.7.
BytesIO
, но да.
- person Marcin; 23.09.2013
StringIO.StringIO
нормально. В 3.x да, вместо этого вы бы хотели использовать io.BytesIO
.
- person abarnert; 23.09.2013
StringIO
просто создает проблему переносимости без всякой причины.
- person Marcin; 23.09.2013
BytesIO
также создает проблему переносимости, поскольку его нет в Python 2.5 (и, IIRC, значительно медленнее, чем StringIO
/cStringIO
до 2.7.2 или около того… но я мог ошибаться, и это вряд ли имеет значение). Иными словами: вы бы стали утверждать, что всегда следует использовать io.open
в 2.x вместо open
для обычных файлов?
- person abarnert; 23.09.2013
2to3
, часто более разумно писать код, совместимый с 2to3
, чем код, совместимый напрямую с 3.x.
- person abarnert; 23.09.2013
StringIO
/BytesIO
, и вы можете получить окончательную строку в конце с помощью метода getvalue
. Если это недостаточно ясно, я напишу ответ.
- person abarnert; 23.09.2013