() translation by (you can also view the original English article)
Si has estado usando computadoras por algún tiempo, probablemente te hayas cruzado con archivo con la extensión .zip. Son archivos especiales que pueden retener el contenido comprimido de muchos otros archivos, carpetas y sub-carpetas. Esto las hace bastante útiles para transferir archivos por internet. ¿Sabías que puedes usar Python para comprimir o extraer archivos?
Este tutorial te enseñará cómo puedes usar el módulo zipfile en Python, para extraer o comprimir archivos individuales om múltiples a la vez.
Comprimiendo Archivos Individuales
Este es sencillo y requiere muy poco código. Comenzamos importando el módulo zipfile y después abrimos el objeto ZipFile en modo escritura especificando el segundo parámetro como 'w'. El primer parámetro es la ruta del archivo mismo. Aquí está el código que necesitas:
1 |
import zipfile |
2 |
|
3 |
jungle_zip = zipfile.ZipFile('C:\\Stories\\Fantasy\\jungle.zip', 'w') |
4 |
jungle_zip.write('C:\\Stories\\Fantasy\\jungle.pdf', compress_type=zipfile.ZIP_DEFLATED) |
5 |
|
6 |
jungle_zip.close() |
Por favor nota que especificaré la ruta en todos los pedazos de código en formato estilo Windows; necesitarás hacer los cambios apropiados si estás en Linux o Mac.
Puedes especificar diferentes métodos de compresión para comprimir archivos. Los métodos más nuevos BZIP2
y LZMA
fueron agregados en Python versión 3.3, y hay algunas otras herramientas también que no soportan estos dos métodos de compresión. Por esta razón, es seguro solo usar el método DEFLATED
. Deberían aún intentar estos métodos para ver la diferencia en el tamaño del archivo comprimido.
Comprimiendo Múltiples Archivos
Esto es ligeramente complejo ya que necesitas iterar sobre todos los archivos. El código de abajo debería comprimir todos los archivos con la extensión pdf en una carpeta dada:
1 |
import os |
2 |
import zipfile |
3 |
|
4 |
fantasy_zip = zipfile.ZipFile('C:\\Stories\\Fantasy\\archive.zip', 'w') |
5 |
|
6 |
for folder, subfolders, files in os.walk('C:\\Stories\\Fantasy'): |
7 |
|
8 |
for file in files: |
9 |
if file.endswith('.pdf'): |
10 |
fantasy_zip.write(os.path.join(folder, file), os.path.relpath(os.path.join(folder,file), 'C:\\Stories\\Fantasy'), compress_type = zipfile.ZIP_DEFLATED) |
11 |
|
12 |
fantasy_zip.close() |
Esta vez, hemos importado el módulo os
y usado su método walk()
para ir sobre los archivos y sub-carpetas dentro de nuestra carpeta original. Solo estoy comprimiendo los archivos pdf en el directorio. También puedes crear diferentes archivos para cada formato usando declaraciones if
.
Si no quieres conservar la estructura de directorio, ahora puedes poner todos los archivos juntos usando la siguiente línea:
1 |
fantasy_zip.write(os.path.join(folder, file), file, compress_type = zipfile.ZIP_DEFLATED) |
El método write()
acepta tres parámetros: El primer parámetro es el nombre de nuestro archivo que queremos comprimir. El segundo parámetro es opcional y te permite especificar un nombre de archivo diferente para el archivo comprimido. Si nada es epecificado, el nombre original es usado.
Extrayendo Todos Los Archivos
Puedes usar el método extractall()
para extraer todos los archivos y carpetas de un archivo zip en el directorio de trabajo actual. También puedes pasar un nombre de carpeta a extractall()
para extraer todos los archivos y carpetas a un folder específico. Si la carpeta que pasaste no existe, este método creará una por ti. Aquí está el código que puedes usar para extraer archivos:
1 |
import zipfile |
2 |
|
3 |
fantasy_zip = zipfile.ZipFile('C:\\Stories\\Fantasy\\archive.zip') |
4 |
fantasy_zip.extractall('C:\\Library\\Stories\\Fantasy') |
5 |
|
6 |
fantasy_zip.close() |
Si quieres extraer múltiples archivos, tendrás que proporcionar los nombres de archivos que quieres extraer como lista.
Extrayendo Archivos Individuales
Esto es similar a extraer múltiples archivos. Una diferencia es que esta vez necesitas proporcionar el nombre de archivo primer y la ruta para extraerlos después. También, necesitas usar el método extract()
en lugar de extractall()
. Aquí está el pedazo de código básico para extraer archivos individuales.
1 |
import zipfile |
2 |
|
3 |
fantasy_zip = zipfile.ZipFile('C:\\Stories\\Fantasy\\archive.zip') |
4 |
fantasy_zip.extract('Fantasy Jungle.pdf', 'C:\\Stories\\Fantasy') |
5 |
|
6 |
fantasy_zip.close() |
Leyendo Archivos Zip
Considera un escenario en donde necesites ver si un archivo zip contiene un archivo específico. En este punto, tu única opción para hacerlo es extrayendo todos los archivos en el archivo. De manera similar, podrías necesitar extraer solo aquellos archivos que son más grandes que un tamaño específico. El módulo zipfile
nos permite es preguntar sobre los contenidos de un archivo sin extraerlo nunca.
Usando el método namelist()
del objeto ZipFile devolverá una lista de miembros de un archivo por nombre. Para obtener información sobre un archivo específico, puedes usar el método getinfo()
del objeto ZipFile. Esto te dará acceso a información específica de ese archivo, como el tamaño comprimido y descomprimido del archivo o su última fecha de modificación. Regresaremos a eso después.
Llamando al método getinfo()
uno por uno en los archivos puede ser un proceso cansado cuando hay muchos archivos que necesitan ser procesados. En este caso, puedes usar el método infolist()
para devolver una lista conteniendo un objeto Zipinfo para cada miembro en el archivo. El orden de estos objetos en la lista es el mismo del zipfiles.
También puedes leer directamente los contenidos de un archivo específico del archivo usando el método read(file)
, en donde file
es el nombre del archivo que pretendes leer. Para hacer esto, el archivo debe ser abierto en modo lectura o anexar.
Para obtener el tamaño comprimido de un archivo individual del archivo, puedes usar el atributo compress_size
. De manera similar, para saber el tamaño descomprimido, puedes usar el atributo file_size
.
El siguiente código usa las propiedades y métodos que discutimos para extraer solo aquellos archivos que tienen un tamaño menor a 1MB.
1 |
import zipfile |
2 |
|
3 |
stories_zip = zipfile.ZipFile('C:\\Stories\\Funny\\archive.zip') |
4 |
|
5 |
for file in stories_zip.namelist(): |
6 |
if stories_zip.getinfo(file).file_size < 1024*1024: |
7 |
stories_zip.extract(file, 'C:\\Stories\\Short\\Funny') |
8 |
|
9 |
stories_zip.close() |
Para saber la fecha y la hora cuando un archivo específico fue modificado, puedes usar el atributo date_time
. Esto devolverá una tupla de seis valores. Los valores serán año, mes, día del mes, horas, minutos y segundos en ese orden específico. El año siempre será mayor qué o igual a 1980, y las horas, minutos y segundos están basados en cero.
1 |
import zipfile |
2 |
|
3 |
stories_zip = zipfile.ZipFile('C:\\Stories\\Funny\\archive.zip') |
4 |
|
5 |
thirsty_crow_info = stories_zip.getinfo('The Thirsty Crow.pdf') |
6 |
|
7 |
print(thirsty_crow_info.date_time) |
8 |
print(thirsty_crow_info.compress_size) |
9 |
print(thirsty_crow_info.file_size) |
10 |
|
11 |
stories_zip.close() |
Esta información sobre el tamaño original y tamaño comprimido de archivo puede ayudarte a decidir si vale la pena comprimir un archivo. Estoy seguro de que puede ser usado en otras situaciones también.
Ideas Finales
Como es evidente en este tutorial, usar el módulo zipfile
para comprimir archivos te da mucha flexibilidad. Puedes comprimir diferentes archivos en un directorio para diferentes archivos basado en su tipo, nombre o tamaño. También puedes decidir si quieres preservar la estructura de directorio o no. De manera similar, extrayendo los archivos, puedes extraerlos a la ubicación que quieras, basado en tu propio criterio como tamaño, etc.
Para ser honesto, también fue bastante emocionante para mi comprimir y extraer archivos escribiendo mi propio código. Espero que hayas disfrutado el tutorial, y si tienes alguna pregunta, por favor házmelo saber en los comentarios.