2010-09-08 18 views
11

estoy usando el siguiente código para extraer un archivo tar:Python tarfile progress output?

import tarfile 
tar = tarfile.open("sample.tar.gz") 
tar.extractall() 
tar.close() 

Sin embargo, me gustaría mantener control sobre los avances en la forma de los archivos que están siendo extraídos por el momento. ¿Cómo puedo hacer esto?

PUNTOS ADICIONALES ADICIONALES: ¿es posible crear un porcentaje del proceso de extracción también? Me gustaría usar eso para que tkinter actualice una barra de progreso. ¡Gracias!

Respuesta

6

Tanto archivo de progreso y pro mundial Gress:

import tarfile 
import io 
import os 

def get_file_progress_file_object_class(on_progress): 
    class FileProgressFileObject(tarfile.ExFileObject): 
     def read(self, size, *args): 
      on_progress(self.name, self.position, self.size) 
      return tarfile.ExFileObject.read(self, size, *args) 
    return FileProgressFileObject 

class TestFileProgressFileObject(tarfile.ExFileObject): 
    def read(self, size, *args): 
     on_progress(self.name, self.position, self.size) 
     return tarfile.ExFileObject.read(self, size, *args) 

class ProgressFileObject(io.FileIO): 
    def __init__(self, path, *args, **kwargs): 
     self._total_size = os.path.getsize(path) 
     io.FileIO.__init__(self, path, *args, **kwargs) 

    def read(self, size): 
     print("Overall process: %d of %d" %(self.tell(), self._total_size)) 
     return io.FileIO.read(self, size) 

def on_progress(filename, position, total_size): 
    print("%s: %d of %s" %(filename, position, total_size)) 

tarfile.TarFile.fileobject = get_file_progress_file_object_class(on_progress) 
tar = tarfile.open(fileobj=ProgressFileObject("a.tgz")) 
tar.extractall() 
tar.close() 
+0

Esto sigue siendo monkeypatching. ':)' –

+0

Gracias tokland, esto funciona :) ¿Alguna forma de obtener un flotador del proceso de extracción global? – FLX

+0

Para ser más específicos, ¿hay alguna forma de obtener el tamaño sin comprimir antes de iniciar el proceso de extracción? – FLX

3

Puede usar extract en lugar de extractall - podrá imprimir los nombres de los miembros a medida que se extraen. Para obtener una lista de miembros, puede usar getmembers.

Una biblioteca Pruebas de progreso se puede encontrar aquí:

Tkinter fragmento:

+1

Si examina el código "extractall" llamadas "extracto ", por lo que no debería haber penalización de velocidad. – tokland

+0

gracias, eliminé mi 'conjetura' sin educación ... – miku

+0

La documentación indica que "el método extract() no se ocupa de varios problemas de extracción. En la mayoría de los casos, debería considerar utilizar el método extractall()". Sin saber cuáles son esos problemas de extracción, dudo en cambiar 'extraer' por' extractall'. –

4

Puede especificar el parámetro members en extractall()

with tarfile.open(<path>, 'r') as tarball: 
    tarball.extractall(path=<some path>, members = track_progress(tarball)) 

def track_progress(members): 
    for member in members: 
     # this will be the current file being extracted 
     yield member 

member son TarInfo objetos, consulte todas las funciones y propiedades here

+2

Para completar esto, después de 'yield member' puede imprimir el nombre o actualizar una barra de progreso. –

2

disponibles Hay una solución fresca aquí que anula el módulo tar como un reemplazo directo y le permite especificar una devolución de llamada para actualizar.

https://github.com/thomaspurchas/tarfile-Progress-Reporter/

actualizada basada en comentario

+0

Esa biblioteca está lejos de estar lista para producción, por ej. uso de variables no asignadas cuando no se pasa una función de progreso ... que pasa una cadena de ruta a extractall falla, porque espera una información de tar (aunque ambas opciones deberían ser posibles) – andsens

1

Para ver qué archivo está siendo extraída, los siguientes trabajó para mí:

import tarfile 

print "Extracting the contents of sample.tar.gz:" 
tar = tarfile.open("sample.tar.gz") 

for member_info in tar.getmembers(): 
    print "- extracting: " + member_info.name 
    tar.extract(member_info) 

tar.close()