2012-05-13 29 views
9

Tengo varios archivos zip que tienen la misma estructura: contienen archivos XML en el nivel raíz. Todos los archivos en cada archivo zip son únicos (no hay duplicados en los archivos zip). Necesito combinar todos los archivos XML de todos los archivos zip en un solo archivo zip (con la misma estructura que los archivos zip originales). ¿Sugerencias de cómo hacer esto mejor? Gracias.Fusionar varios archivos zip en un solo archivo zip en Python

+3

¿Desempaquete todas y haga una nueva? – sarnold

+3

Ese sería el enfoque más obvio. También puede elegir uno como el archivo zip final, extraer los archivos de los demás y agregarlos a la final, pero no estoy seguro de que sea más rápido. – jgritty

+0

Gracias @sarnold. Yo también estaba pensando en este enfoque, pero no estaba seguro de si había una forma más elegante de hacerlo. –

Respuesta

11

Ésta es la versión más corta que podía llegar a:

>>> 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() 

Sin probar la alternativa, para mí este es el mejor (y probablemente más evidente también!) Solución porque - suponiendo que ambos archivos zip contiene la la misma cantidad de datos, este método requiere la descompresión y la nueva compresión de solo la mitad (1 archivo).

PD: La comprensión de listas solo sirve para mantener las instrucciones en una línea en la consola (lo que acelera la depuración). Un buen código pitónico requeriría un bucle for adecuado, dado que la lista resultante no sirve para nada ...

HTH!

+0

Gracias, aunque tendré una cantidad variable de archivos comprimidos, así que necesito un enfoque más genérico. –

+1

@DaveCrumbacher: a menos que no te haya entendido bien, todo lo que tienes que hacer para utilizar este enfoque para fusionar más de un archivo es agregar un bucle: 'para zfile en (z2, z3, z4, ...)' ... . ¿O me estoy perdiendo algo? – mac

+0

Sí, @mac, tienes razón. Gracias. –

6

Esto es lo que se me ocurrió, gracias a @mac. Tenga en cuenta que, de la forma en que esto se implementa actualmente, se modifica el primer archivo zip para que contenga todos los archivos de los otros archivos 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()' también es un administrador de contexto, por lo que podría reemplazar su 'z1.close()' con un 'con z.ZipFile (zip [0], 'a') como z1:' y sangría el código subsiguiente. Lo mismo con los objetos de lectura. – glglgl

+2

Gracias @glglgl. He actualizado mi respuesta para reflejar este enfoque. –

Cuestiones relacionadas