Existe-t-il une bibliothèque Python qui permet la manipulation d'archives Zip en mémoire, sans avoir à utiliser de véritables fichiers disque?
La bibliothèque ZipFile ne vous permet pas de mettre à jour l'archive. La seule façon semble être de l'extraire dans un répertoire, d'apporter vos modifications et de créer un nouveau Zip à partir de ce répertoire. Je souhaite modifier les archives Zip sans accès au disque, car je vais les télécharger, apporter des modifications et les télécharger à nouveau, donc je n'ai aucune raison de les stocker.
Quelque chose de similaire à ZipInputStream/ZipOutputStream de Java ferait l'affaire, bien que n'importe quelle interface qui évite l'accès au disque convienne.
Selon les documents 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.
Donc, pour ouvrir le fichier en mémoire, créez simplement un objet de type fichier (peut-être en utilisant BytesIO ).
file_like_object = io.BytesIO(my_Zip_data)
zipfile_ob = zipfile.ZipFile(file_like_object)
De l'article Zip en mémoire en Python :
Ci-dessous est un de mes articles de mai 2008 sur la fermeture éclair en mémoire avec Python, republié depuis la fermeture de Posterous.
J'ai récemment remarqué qu'un composant payant est disponible pour les fichiers Zip en mémoire avec Python. Considérant que c'est quelque chose qui devrait être gratuit, j'ai rassemblé le code suivant. Il n'a subi que des tests très basiques, donc si quelqu'un trouve des erreurs, faites-le moi savoir et je le mettrai à jour.
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 __== "__main__":
# Run a test
imz = InMemoryZip()
imz.append("test.txt", "Another test").append("test2.txt", "Still another")
imz.writetofile("test.Zip")
L'exemple fourni par Ethier présente plusieurs problèmes, dont certains majeurs:
InMemoryZip
Une version mise à jour est disponible si vous installez ruamel.std.zipfile
(dont je suis l'auteur). Après
pip install ruamel.std.zipfile
ou en incluant le code de la classe de ici , vous pouvez faire:
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")
Vous pouvez également écrire le contenu en utilisant imz.data
à tout endroit dont vous avez besoin.
Vous pouvez également utiliser l'instruction with
, et si vous fournissez un nom de fichier, le contenu du Zip sera écrit en quittant ce contexte:
with zipfile.InMemoryZipFile('test.Zip') as imz:
imz.append("test.txt", "Another test").append("test2.txt", "Still another")
en raison de l'écriture différée sur le disque, vous pouvez réellement lire à partir d'un ancien test.Zip
dans ce contexte.
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())