make - zip deflated python
Biblioteca zip en memoria de Python (4)
¿Hay una biblioteca de Python que permita la manipulación de archivos comprimidos en la memoria, sin tener que usar archivos de disco reales?
La biblioteca de ZipFile no le permite actualizar el archivo. La única forma parece ser extraerlo a un directorio, hacer los cambios y crear un nuevo archivo comprimido desde ese directorio. Quiero modificar los archivos comprimidos sin acceso al disco, porque los descargaré, realizaré cambios y los cargaré de nuevo, por lo que no tengo motivos para almacenarlos.
Algo similar a ZipInputStream / ZipOutputStream de Java haría el truco, aunque cualquier interfaz en absoluto que evite el acceso al disco estaría bien.
PYTHON 3
import io
import zipfile
zip_buffer = io.BytesIO()
with zipfile.ZipFile(zip_buffer, "a", zipfile.ZIP_DEFLATED, False) as zip_file:
for file_name, data in [(''1.txt'', io.BytesIO(b''111'')), (''2.txt'', io.BytesIO(b''222''))]:
zip_file.writestr(file_name, data.getvalue())
with open(''C:/1.zip'', ''wb'') as f:
f.write(zip_buffer.getvalue())
De acuerdo con los documentos de Python :
class zipfile.ZipFile(file[, mode[, compression[, allowZip64]]])
Open a ZIP file, where file can be either a path to a file (a string) or a file-like object.
Por lo tanto, para abrir el archivo en la memoria, simplemente cree un objeto similar a un archivo (quizás usando BytesIO ).
file_like_object = io.BytesIO(my_zip_data)
zipfile_ob = zipfile.ZipFile(file_like_object)
Del artículo In-Memory Zip in Python :
A continuación se muestra un post mío desde mayo de 2008 en zipping en la memoria con Python, re-publicado ya que Posterous está cerrando.
Recientemente noté que hay un componente de pago disponible para comprimir archivos en memoria con Python. Considerando que esto es algo que debería ser gratis, armé el siguiente código. Solo ha pasado por pruebas muy básicas, por lo que si alguien encuentra algún error, avíseme y lo actualizaré.
import zipfile
import StringIO
class InMemoryZip(object):
def __init__(self):
# Create the in-memory file-like object
self.in_memory_zip = StringIO.StringIO()
def append(self, filename_in_zip, file_contents):
''''''Appends a file with name filename_in_zip and contents of
file_contents to the in-memory zip.''''''
# Get a handle to the in-memory zip in append mode
zf = zipfile.ZipFile(self.in_memory_zip, "a", zipfile.ZIP_DEFLATED, False)
# Write the file to the in-memory zip
zf.writestr(filename_in_zip, file_contents)
# Mark the files as having been created on Windows so that
# Unix permissions are not inferred as 0000
for zfile in zf.filelist:
zfile.create_system = 0
return self
def read(self):
''''''Returns a string with the contents of the in-memory zip.''''''
self.in_memory_zip.seek(0)
return self.in_memory_zip.read()
def writetofile(self, filename):
''''''Writes the in-memory zip to a file.''''''
f = file(filename, "w")
f.write(self.read())
f.close()
if __name__ == "__main__":
# Run a test
imz = InMemoryZip()
imz.append("test.txt", "Another test").append("test2.txt", "Still another")
imz.writetofile("test.zip")
El ejemplo proporcionado por Ethier tiene varios problemas, algunos de ellos importantes:
- no funciona para datos reales en Windows. Un archivo ZIP es binario y sus datos siempre deben escribirse con un archivo abierto ''wb''
- el archivo ZIP se anexa para cada archivo, esto es ineficiente. Solo se puede abrir y mantener como un atributo
InMemoryZip
- la documentación indica que los archivos ZIP deben cerrarse explícitamente, esto no se hace en la función de adición (probablemente funciona (por ejemplo) porque zf sale del alcance y cierra el archivo ZIP)
- El indicador create_system se establece para todos los archivos en el archivo zip cada vez que se agrega un archivo en lugar de solo una vez por archivo.
- en Python <3 cStringIO es mucho más eficiente que StringIO
- no funciona en Python 3 (el artículo original era anterior a la versión 3.0, pero para el momento en que se publicó el código 3.1 había estado fuera durante mucho tiempo).
Hay una versión actualizada disponible si instala ruamel.std.zipfile
(del cual soy el autor). Después
pip install ruamel.std.zipfile
o incluyendo el código para la clase desde here , puedes hacer:
import ruamel.std.zipfile as zipfile
# Run a test
zipfile.InMemoryZipFile()
imz.append("test.txt", "Another test").append("test2.txt", "Still another")
imz.writetofile("test.zip")
Alternativamente, puede escribir los contenidos usando imz.data
en cualquier lugar que necesite.
También puede usar la instrucción with
, y si proporciona un nombre de archivo, el contenido del ZIP se escribirá al salir de ese contexto:
with zipfile.InMemoryZipFile(''test.zip'') as imz:
imz.append("test.txt", "Another test").append("test2.txt", "Still another")
debido a la escritura retrasada en el disco, puedes leer de un antiguo test.zip
dentro de ese contexto.