Gibt es eine Python-Bibliothek, mit der Zip-Archive im Speicher bearbeitet werden können, ohne dass tatsächliche Festplattendateien verwendet werden müssen?
In der ZipFile-Bibliothek können Sie das Archiv nicht aktualisieren. Die einzige Möglichkeit scheint darin zu bestehen, es in ein Verzeichnis zu extrahieren, Änderungen vorzunehmen und eine neue Zip-Datei aus diesem Verzeichnis zu erstellen. Ich möchte Zip-Archive ohne Festplattenzugriff ändern, da ich sie herunterladen, Änderungen vornehmen und erneut hochladen werde, sodass ich keinen Grund habe, sie zu speichern.
Etwas Ähnliches wie Javas ZipInputStream / ZipOutputStream würde den Trick machen, obwohl jede Schnittstelle, die den Festplattenzugriff vermeidet, in Ordnung wäre.
Antworten:
Laut den Python-Dokumenten :
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.
Um die Datei im Speicher zu öffnen, erstellen Sie einfach ein dateiähnliches Objekt (möglicherweise mit BytesIO ).
quelle
Aus dem Artikel In-Memory Zip in Python :
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")
quelle
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())
quelle
data
kann entweder Bytes oder Strings sein und dies funktionierte perfekt unter Ubuntu und Python 3.6Das von Ethier bereitgestellte Beispiel weist mehrere Probleme auf, von denen einige schwerwiegend sind:
InMemoryZip
Attribut beibehalten werdenEine aktualisierte Version ist verfügbar, wenn Sie installieren
ruamel.std.zipfile
(von denen ich der Autor bin). Nachoder den Code für die Klasse einschließlich von hier können Sie tun:
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")
Alternativ können Sie den Inhalt
imz.data
an einen beliebigen Ort schreiben .Sie können die
with
Anweisung auch verwenden. Wenn Sie einen Dateinamen angeben, wird der Inhalt der ZIP-Datei beim Verlassen dieses Kontexts geschrieben:with zipfile.InMemoryZipFile('test.zip') as imz: imz.append("test.txt", "Another test").append("test2.txt", "Still another")
Aufgrund des verzögerten Schreibens auf eine Disc können Sie
test.zip
in diesem Kontext tatsächlich von einem alten lesen .quelle