2010-09-08 15 views
11

Sto utilizzando il seguente codice per estrarre un file tar:Output di avanzamento tarfile Python?

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

Tuttavia, mi piacerebbe tenere sotto controllo i progressi nella forma di cui i file vengono estratti in questo momento. Come posso fare questo?

PUNTI BONUS EXTRA: è possibile creare anche una percentuale del processo di estrazione? Mi piacerebbe usare quello per tkinter per aggiornare una barra di avanzamento. Grazie!

risposta

6

Sia di file-progresso e Global PRO 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

Questo è ancora monkeypatching. ':)' –

+0

Grazie a tokland, questo funziona :) Qualsiasi modo di ottenere una virgola del processo di estrazione generale? – FLX

+0

Per essere più specifici, c'è un modo per ottenere le dimensioni non compresse prima di iniziare il processo di estrazione? – FLX

3

È possibile utilizzare extract anziché extractall - è possibile stampare i nomi dei membri mentre vengono estratti. Per ottenere un elenco di membri, è possibile utilizzare getmembers.

Una biblioteca testuale progressbar può essere trovato qui:

Tkinter frammento:

+1

Guardando il codice "extractall" chiama "estratto ", quindi non dovrebbe esserci penalizzazione della velocità. – tokland

+0

grazie, rimosso la mia "supposizione" ignorante ... – miku

+0

Note sulla documentazione "Il metodo extract() non si occupa di diversi problemi di estrazione, nella maggior parte dei casi dovresti prendere in considerazione l'utilizzo del metodo extractall().". Senza sapere quali sono questi problemi di estrazione, sono titubante a scambiare semplicemente "estratto" per "extractall". –

4

È possibile specificare il parametro members in 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 sono TarInfo oggetti, vedere tutte le funzioni e le proprietà here

+2

Per compilarlo, dopo 'yield member' è possibile stampare il nome o aggiornare una barra di avanzamento. –

2

disponibili C'è una soluzione fredda qui che sostituisce il modulo tarfile come una sostituzione drop-in e consente di specificare una richiamata per l'aggiornamento.

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

aggiornato sulla base di commento

+0

Quella libreria è lontana dalla produzione pronta, ad es. utilizzo di variabili non assegnate quando non si passa a una funzione di avanzamento ... il passaggio di una stringa di percorso a extractall non riesce, perché si aspetta un tarinfo (anche se entrambe le opzioni dovrebbero essere possibili) – andsens

1

Per vedere quale file è attualmente in fase di estratto, i seguenti ha lavorato per me:

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