2010-09-08 4 views
11

Я использую следующий код, чтобы извлечь файл дегтя:Python tarfile progress output?

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

Однако, я хотел бы, чтобы следить за прогрессом в виде файлов которые добывают в данный момент. Как я могу это сделать?

EXTRA BONUS POINTS: возможно ли создать процент от процесса извлечения? Я хотел бы использовать это для tkinter для обновления индикатора выполнения. Благодаря!

ответ

6

Оба файла прогресс и глобальные про гресс:

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

Это все еще monkeypatching. ':)' –

+0

Спасибо tokland, это работает :) Любой способ получить поплавок полного процесса извлечения? – FLX

+0

Чтобы быть более конкретным, есть способ получить несжатый размер перед началом процесса извлечения? – FLX

3

Вы можете использовать extract вместо extractall - вы сможете печатать имена участников при их извлечении. Чтобы получить список участников, вы можете использовать getmembers.

библиотека текстуальное ProgressBar можно найти здесь:

Tkinter сниппет:

+1

Глядя на код "extractall" называет «экстракт », поэтому не должно быть штрафов за скорость. – tokland

+0

спасибо, удалил мою необразованную «гадание» ... – miku

+0

Примечания к документации «Метод extract() не заботится о нескольких проблемах с извлечением. В большинстве случаев вам следует рассмотреть метод extractall().». Не зная, что такое проблемы с добычей, я не решаюсь просто поменять «extract» на 'extractall'. –

4

Вы можете задать параметр members в 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 являются TarInfo объекты, увидеть все доступные функции и свойства here

+2

Чтобы заполнить это, после 'yield member' вы можете распечатать имя или обновить индикатор выполнения. –

2

Там прохладное решение здесь переопределяет модуль файл обработан в качестве замены для замены и позволяет указать обратный вызов для обновления.

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

обновляется на основе комментариев

+0

Эта библиотека далека от готовой продукции, например. использование неназначенных переменных, когда не передается функция прогресса ... передача строки пути в extractall не выполняется, поскольку она ожидает tarinfo (хотя оба варианта должны быть возможны) – andsens

1

Чтобы узнать, какой файл в настоящее время извлечены, следующие работал для меня:

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() 
Смежные вопросы