2012-05-13 2 views
9

Ho più file zip che hanno la stessa struttura - contengono file XML a livello di root. Tutti i file in ogni file zip sono unici (nessun duplicato tra i file zip). Ho bisogno di combinare tutti i file XML da tutti i file zip in un unico file zip (con la stessa struttura dei file zip originali). Suggerimenti su come andare meglio nel fare questo? Grazie.Unire più file zip in un singolo file zip in Python

+3

Disimballare tutti e crearne uno nuovo? – sarnold

+3

Questo sarebbe l'approccio più ovvio. Puoi anche sceglierne uno come zipfile finale, estrarre i file dagli altri e aggiungerli a quello finale, ma non è sicuro che sarà più veloce. – jgritty

+0

Grazie @sarnold. Anch'io pensavo a questo approccio, ma non ero sicuro se esistesse un modo più elegante per farlo. –

risposta

11

Questa è la versione più breve ho potuto venire con:

>>> import zipfile as z 
>>> z1 = z.ZipFile('z1.zip', 'a') 
>>> z2 = z.ZipFile('z2.zip', 'r') 
>>> z1.namelist() 
['a.xml', 'b.xml'] 
>>> z2.namelist() 
['c.xml', 'd.xml'] 
>>> [z1.writestr(t[0], t[1].read()) for t in ((n, z2.open(n)) for n in z2.namelist())] 
[None, None] 
>>> z1.namelist() 
['a.xml', 'b.xml', 'c.xml', 'd.xml'] 
>>> z1.close() 

Senza prova l'alternativa, per me questo è il migliore (e probabilmente più ovvio troppo!) Soluzione perché - supponendo che entrambi i file zip contiene il stessa quantità di dati, questo metodo richiede la decompressione e la ricompressione di solo la metà di esso (1 file).

PS: La comprensione delle liste serve solo a mantenere le istruzioni su una riga nella console (che velocizza il debugging). Un buon codice pythonic richiederebbe un ciclo appropriato for, dato che l'elenco risultante non ha alcuno scopo ...

HTH!

+0

Grazie, anche se avrò un numero variabile di file zip, quindi ho bisogno di un approccio più generico. –

+1

@DaveCrumbacher: a meno che non ti abbia frainteso, tutto ciò che devi fare per usare questo approccio per unire più di un file, è aggiungere un ciclo: 'per zfile in (z2, z3, z4, ...)' ... . O mi sta sfuggendo qualcosa? – mac

+0

Sì, @mac, hai ragione. Grazie. –

6

Ecco cosa mi è venuto in mente, grazie a @mac. Si noti che il modo in cui viene attualmente implementato il primo file zip viene modificato per contenere tutti i file degli altri file zip.

import zipfile as z 

zips = ['z1.zip', 'z2.zip', 'z3.zip'] 

""" 
Open the first zip file as append and then read all 
subsequent zip files and append to the first one 
""" 
with z.ZipFile(zips[0], 'a') as z1: 
    for fname in zips[1:]: 
     zf = z.ZipFile(fname, 'r') 
     for n in zf.namelist(): 
      z1.writestr(n, zf.open(n).read()) 
+5

'zipfile.ZipFile()' è anche un gestore di contesto, quindi puoi sostituire il tuo 'z1.close()' con un 'con z.ZipFile (zips [0], 'a') come z1:' e indent il codice successivo. Lo stesso con gli oggetti di lettura. – glglgl

+2

Grazie @glglgl. Ho aggiornato la mia risposta per riflettere questo approccio. –