Распаковка фрагментов байтов из S3 с помощью iter_chunks () - PullRequest
1 голос
/ 05 апреля 2020

У меня возникают проблемы с распаковкой фрагментов байтов, которые я читаю с S3, используя метод iter_chunks() из boto3. Стратегия распаковки файла chunk-by-chunk исходит из этой проблемы .

Код выглядит следующим образом:

dec = zlib.decompressobj(32 + zlib.MAX_WBITS)
for chunk in app.s3_client.get_object(Bucket=bucket, Key=key)["Body"].iter_chunks(2 ** 19):
    data = dec.decompress(chunk)
    print(len(chunk), len(data))

# 524288 65505
# 524288 0
# 524288 0
# ...

Этот код изначально печатает значение 65505 с последующим 0 для каждой последующей итерации. Насколько я понимаю, этот код должен разархивировать каждый сжатый фрагмент, а затем распечатать длину несжатой версии.

Есть что-то, что я пропускаю?

1 Ответ

1 голос
/ 20 апреля 2020

Кажется, что ваш входной файл - это блок gzip (bgzip http://www.htslib.org/doc/bgzip.html), потому что у вас есть декодированный блок данных размером 65 КБ.

Файлы GZip можно объединять вместе (см. https://www.gnu.org/software/gzip/manual/gzip.html#Advanced -usage ) и Block GZip используют это для объединения блоков одного и того же файла, так что при использовании ассоциированного индекса необходимо декодировать только указанный c блок, содержащий интересующую информацию.

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

# source is a block gzip file see http://www.htslib.org/doc/bgzip.html
dec = zlib.decompressobj(32+zlib.MAX_WBITS)
for chunk in raw:
    # decompress this chunk of data
    data = dec.decompress(chunk)
    # bgzip is a concatenation of gzip files
    # if there is stuff in this chunk beyond the current block
    # it needs to be processed
    while len(dec.unused_data):
        # end of one block
        leftovers = dec.unused_data
        # create a new decompressor
        dec = zlib.decompressobj(32+zlib.MAX_WBITS)
        #decompress the leftovers
        data = data+dec.decompress(leftovers)
    # TODO handle data
...