Как получить время, необходимое для распаковки больших файлов bz2? - PullRequest
0 голосов
/ 08 февраля 2019

Мне нужно обработать большие файлы bz2 (~ 6G), используя Python, распаковывая его построчно, используя BZ2File.readline().Проблема в том, что я хочу знать, сколько времени требуется для обработки всего файла.

Я провел много поисков, пытался определить фактический размер распакованного файла, чтобы узнать процент обработки нана лету, и, следовательно, оставшееся время, в то время как обнаруживается, что кажется невозможным узнать размер распакованного файла без его предварительного распаковывания (https://stackoverflow.com/a/12647847/7876675).

Кроме того, распаковка файла требует много памяти, распаковказанимает много времени само по себе. Итак, кто-нибудь может помочь мне получить оставшееся время обработки на лету?

Ответы [ 2 ]

0 голосов
/ 09 февраля 2019

С помощью другого ответа наконец-то нашел решение.Идея состоит в том, чтобы использовать размер обработанного сжатого файла, общий размер сжатого файла и время, используемое для оценки оставшегося времени.Для этого

  1. считывает сжатый файл как объект байта в память: byte_data, что довольно быстро
  2. вычисляет размер byte_data, используя total_size = len(byte_data)
  3. обтекание byte_data как byte_f = io.BytesIO(byte_data)
  4. обтекание byte_f как bz2f = bz2.BZ2File(byte_f)
  5. во время обработки, используйте pos = byte_f.tell() для получения текущей позиции в сжатый file
  6. вычислить точный процент обработанного percent = pos/total_size
  7. используемого времени записи и рассчитать оставшееся время

Через несколько секунд оценка может стать довольно точной:

0.01% processed, 2.00s elapsed, 17514.27s remaining...
0.02% processed, 4.00s elapsed, 20167.48s remaining...
0.03% processed, 6.00s elapsed, 21239.60s remaining...
0.04% processed, 8.00s elapsed, 21818.91s remaining...
0.05% processed, 10.00s elapsed, 22180.76s remaining...
0.05% processed, 12.00s elapsed, 22427.78s remaining...
0.06% processed, 14.00s elapsed, 22661.80s remaining...
0.07% processed, 16.00s elapsed, 22840.45s remaining...
0.08% processed, 18.00s elapsed, 22937.07s remaining...
....
99.97% processed, 22704.28s elapsed, 6.27s remaining...
99.98% processed, 22706.28s elapsed, 4.40s remaining...
99.99% processed, 22708.28s elapsed, 2.45s remaining...
100.00% processed, 22710.28s elapsed, 0.54s remaining...
0 голосов
/ 09 февраля 2019

Вы можете оценить оставшееся время на основе потребления из сжатых данных вместо производства несжатых данных.Результат будет примерно таким же, если данные будут относительно однородными.(Если это не так, то использование ввода или вывода в любом случае не даст точной оценки.)

Вы можете легко найти размер сжатого файла и использовать время, потраченное на сжатый файл.данные для оценки времени обработки оставшихся сжатых данных.

Вот простой пример использования объекта BZ2Decompress для одновременной работы с входным блоком, показывая ход чтения (Python 3, получая имя файла из командной строки):

# Decompress a bzip2 file, showing progress based on consumed input.

import sys
import os
import bz2
import time

def proc(input):
    """Decompress and process a piece of a compressed stream"""
    dat = dec.decompress(input)
    got = len(dat)
    if got != 0:    # 0 is common -- waiting for a bzip2 block
        # process dat here
        pass
    return got

# Get the size of the compressed bzip2 file.
path = sys.argv[1]
size = os.path.getsize(path)

# Decompress CHUNK bytes at a time.
CHUNK = 16384
totin = 0
totout = 0
prev = -1
dec = bz2.BZ2Decompressor()
start = time.time()
with open(path, 'rb') as f:
    for chunk in iter(lambda: f.read(CHUNK), b''):
        # feed chunk to decompressor
        got = proc(chunk)

        # handle case of concatenated bz2 streams
        if dec.eof:
            rem = dec.unused_data
            dec = bz2.BZ2Decompressor()
            got += proc(rem)

        # show progress
        totin += len(chunk)
        totout += got
        if got != 0:    # only if a bzip2 block emitted
            frac = round(1000 * totin / size)
            if frac != prev:
                left = (size / totin - 1) * (time.time() - start)
                print(f'\r{frac / 10:.1f}% (~{left:.1f}s left) ', end='')
                prev = frac

# Show the resulting size.
print(end='\r')
print(totout, 'uncompressed bytes')
...