Я знаю, как извлечь zip-архив с помощью Python, но как именно отображать ход этого извлечения в процентах?
Извлечь ZipFile с помощью Python, отобразить процент выполнения?
Ответы (3)
метод извлечения не обеспечивает обратный вызов для этого, поэтому нужно было бы использовать getinfo
, чтобы получить несжатый размер e, а затем открыть файл, прочитанный из него в блоках, и записать его в то место, куда вы хотите, чтобы файл пошел, и обновить процент, также нужно будет восстановить mtime, если это требуется, например:
import zipfile
z = zipfile.ZipFile(some_source)
entry_info = z.getinfo(entry_name)
i = z.open(entry_name)
o = open(target_name, 'w')
offset = 0
while True:
b = i.read(block_size)
offset += len(b)
set_percentage(float(offset)/float(entry_info.file_size) * 100.)
if b == '':
break
o.write(b)
i.close()
o.close()
set_attributes_from(entry_info)
это извлекает от entry_name
до target_name
большая часть этого также делается shutil.copyfileobj
, но у него также нет обратного вызова для прогресса
источник вызова метода ZipFile.extract
_extract_member
использует:
source = self.open(member, pwd=pwd)
target = file(targetpath, "wb")
shutil.copyfileobj(source, target)
source.close()
target.close()
где элемент был преобразован из имени в объект ZipInfo с помощью getinfo(member)
, если он не был объектом ZipInfo
some/path/to/some/file
будет именем файла, а для каталогов нет записей
- person Dan D.; 03.12.2010
Я предлагаю использовать tqdm
, вы можете установить его с помощью pip
следующим образом:
pip install tqdm
Затем вы можете использовать его напрямую так:
>>> with zipfile.ZipFile(some_source) as zf:
... for member in tqdm(zf.infolist(), desc='Extracting '):
... try:
... zf.extract(member, target_path)
... except zipfile.error as e:
... pass
Это произведет что-то вроде этого:
Extracting : 100%|██████████| 60.0k/60.0k [14:56<00:00, 66.9File/s]
tqdm
. Вы можете легко найти процент, зная индекс файла. Например, предположим, что у вас есть 100 файлов, и сейчас вы извлекаете 4-й файл, значит, вы сделали 4%. Простой!!
- person Anwarvic; 01.03.2020
Извините, что немного поздно увидел это. Была похожая проблема, нужен эквивалент zipfile.Zipfile.extractall
. Если у вас есть tqdm>=4.40.0
(которую я выпустил больше года назад), то:
from os import fspath
from pathlib import Path
from shutil import copyfileobj
from zipfile import ZipFile
from tqdm.auto import tqdm # could use from tqdm.gui import tqdm
from tqdm.utils import CallbackIOWrapper
def extractall(fzip, dest, desc="Extracting"):
"""zipfile.Zipfile(fzip).extractall(dest) with progress"""
dest = Path(dest).expanduser()
with ZipFile(fzip) as zipf, tqdm(
desc=desc, unit="B", unit_scale=True, unit_divisor=1024,
total=sum(getattr(i, "file_size", 0) for i in zipf.infolist()),
) as pbar:
for i in zipf.infolist():
if not getattr(i, "file_size", 0): # directory
zipf.extract(i, fspath(dest))
else:
with zipf.open(i) as fi, open(fspath(dest / i.filename), "wb") as fo:
copyfileobj(CallbackIOWrapper(pbar.update, fi), fo)
ZipInfo.file_size
- person Novikov   schedule 03.12.2010