Разбить файл на переменные с размером чтения python - PullRequest
0 голосов
/ 05 марта 2020

Я пытаюсь прочитать файл кусками разного размера, чтобы вычислить etag файла и сравнить его с etags на ресурсе s3.

Я понимаю, что это вопрос, который задавался ранее, но все ответы Я видел, что в этом случае используется чанки одинакового размера, которые согласуются в процессе обработки.

Я пытаюсь взять файл любого размера и для первых 5 ГБ этого файла вычислить md5 для каждого 5 МБ фрагмента. Затем для следующих 25 ГБ файла рассчитайте md5 для каждого блока 25 МБ. И для окончательного объема файла рассчитайте md5 для каждого блока 125 МБ.

Я полагаю, что это разбивается на: 1000 фрагментов от 5 МБ до 5 ГБ, следующие 1000 блоков от 25 МБ до 25 ГБ (или чтение до 30 ГБ) ) последние 8000 фрагментов по 125 МБ каждый до 1 ТБ

Протокол S3 ограничивает количество фрагментов до 10000 макс.

Таким образом, для файла размером 49,9 ГБ я бы получил 2136 объединенных частей и md5

Причина этого в том, что загрузка на устройство s3 была сделана с использованием Goofys, который загружает на основе этой схемы чанкинга.

Я пытался использовать вложенные циклы while (где мое условие не было ' не работает должным образом), и моя настоящая попытка использует операторы if ...

Когда я теряюсь, я проверяю, что file.read (chunk_size) изменяется при достижении пороговых значений размера, пока весь файл не будет читать.

1 Ответ

0 голосов
/ 05 марта 2020

Оказывается, я сделал неверное предположение, и решение оказалось проще, чем я думал. Я делал это слишком сложно.

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

Вот мое решение:

import os, hashlib
from hashlib import md5

def etag_calc(inputfile):

    md5_digest = []
    partsize1 = 5*1024*1024
    partsize2 = 25*1024*1024
    partsize3 = 125*1024*1024

    with open(inputfile, 'rb') as f:
        for chunk in iter(lambda: f.read(partsize1), b''):
            md5_digest.append(hashlib.md5(chunk).digest())
            if len(md5_digest) < 1000:
                continue
            else:
                break

        for chunk in iter(lambda: f.read(partsize2), b''):
            md5_digest.append(hashlib.md5(chunk).digest())
            if len(md5_digest) < 2000:
                continue
            else:
                break

        for chunk in iter(lambda: f.read(partsize3), b''):
            md5_digest.append(hashlib.md5(chunk).digest())
            if len(md5_digest) < 10000:
                continue
            else:
                break

    return hashlib.md5(b''.join(md5_digest)).hexdigest() + '-' + str(len(md5_digest))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...