Прочитайте zip-файлы из amazon s3, используя boto3 и python

1

У меня есть ведро s3, в котором нет большого количества zip файлов, имеющих размер в GB. Мне нужно рассчитать всю длину данных zip файлов. Я прохожу через boto3, но не понял. Я не уверен, может ли он напрямую читать zip файл или нет, но у меня есть process-

  1. Соединитесь с ведром.
  2. Прочтите zip файлы из папки bucket (скажем, папка Mydata).
  3. Извлеките zip файлы в другую папку с именем Extracteddata.
  4. Прочитайте папку Extracteddata и выполните действия над файлами.

Примечание. Ничего не следует загружать на локальное хранилище. Весь процесс продолжается с S3 до S3. Любые предложения приветствуются.

  • 0
    Когда вы говорите: «Ничто не должно загружаться в локальное хранилище», вас беспокоит загрузка или локальное хранилище ? Потому что я почти уверен, что можно избежать последнего, передавая файл из S3 в память и разархивируя его в памяти, но избежать первого невозможно.
  • 0
    Все о времени, которое потребуется для загрузки. Мне не нужны данные. Я просто хочу, чтобы zip-файл с именем hello.zip содержал 44 JSON-файла. Цель состоит в том, чтобы получить 44 на выходе.
Показать ещё 4 комментария
Теги:
amazon-web-services
amazon-s3
boto3

2 ответа

3
Лучший ответ

То, что вы хотите сделать, невозможно, как объяснил ответ Джона Ротенштейна. Вам необходимо загрузить zipfile - не обязательно в локальное хранилище, но, по крайней мере, в локальную память, используя вашу локальную пропускную способность. Нет способа запустить какой-либо код на S3.

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

Если бы вы могли просто загрузить, скажем, 8 КБ файла, а не всего 5 ГБ, это было бы достаточно хорошо? Если это так - и если вы готовы немного поработать, тогда вам повезло. Что делать, если вам нужно было скачать, скажем, 1 МБ, но может сделать намного меньше работы?


Если 1MB не звучит слишком плохо, и вы готовы немного взломать:

Единственное, что вы хотите, это количество файлов в zipfile. Для zipfile вся эта информация доступна в центральном каталоге, очень маленьком фрагменте данных в самом конце файла.

И если у вас есть весь центральный каталог, даже если вам не хватает остальной части файла, zipfile модуль в stdlib справится с этим просто отлично. Это не документировано, но, по крайней мере, в версиях, включенных в последние версии CPython и PyPy 3.x, это определенно будет.

Итак, что вы можете сделать, так это:

  • Сделайте запрос HEAD чтобы получить только заголовки. (В boto вы делаете это с помощью head_object.)
  • Извлеките размер файла из заголовка Content-Length.
  • Сделайте запрос GET с заголовком Range чтобы загружать, скажем, size-1048576 до конца. (В boto, я считаю, вам, возможно, придется вызвать get_object вместо одного из методов download*, и вам нужно get_object форматировать значение заголовка Range.)

Теперь, предполагая, что у вас есть последний 1 МБ в буфере buf:

z = zipfile.ZipFile(io.BytesIO(buf))
count = len(z.filelist)

Обычно 1 МБ более чем достаточно. Но как насчет того, когда это не так? Ну, здесь, где все становится немного взломанным. Модуль zipfile знает, сколько еще байтов вам нужно, но единственное место, которое оно дает вам, в тексте описания исключения. Так:

try:
    z = zipfile.ZipFile(io.BytesIO(buf))
except ValueError as e:
    m = re.match(r'negative seek value -(\d+)', z.args[0])
    if not m:
        raise
    extra = int(m.group(1))
    # now go read from size-1048576-extra to size-1048576, prepend to buf, try again
count = len(z.filelist)

Если 1MB уже звучит как слишком большая пропускная способность, или вы не хотите полагаться на недокументированное поведение модуля zipfile, вам просто нужно немного поработать.

Почти в каждом случае вам даже не нужен весь центральный каталог, а всего total number of entries полей total number of entries в end of central directory record - даже меньший фрагмент данных в самом конце центрального каталога.

Итак, делайте то же самое, что и выше, но читайте только последние 8 КБ, а не последние 1 МБ.

А затем, основываясь на спецификации формата zip, напишите свой собственный синтаксический анализатор.

Конечно, вам не нужно писать полный парсер или даже близко к нему. Вам просто нужно достаточно, чтобы иметь дело с полями от total number of entries до конца. Все из них являются полями фиксированного размера, за исключением zip64 extensible data sector и/или .ZIP file comment.

Иногда (например, для zip файлов с огромными комментариями) вам нужно будет прочитать больше данных, чтобы получить счет. Это должно быть довольно редко, но если по какой-то причине это становится более распространенным с вашими zip файлами, вы можете просто изменить, что 8192 догадывается о чем-то большем.

  • 0
    что за буф держит? с get_object вне здесь - paste.org/94308
  • 0
    Основываясь на документах, поле Body возвращаемое get_object представляет собой [ botocore.request.StreamingBody ] (botocore.response.StreamingBody), так что вы посмотрите это в документах и узнаете, как считывать из него буфер. И что бы вы ни читали, вот что такое buf .
Показать ещё 1 комментарий
0

Это невозможно.

Вы можете загружать файлы на Amazon S3, и вы можете скачивать файлы. Вы можете запросить список объектов и получить метаданные об объектах. Однако Amazon S3 не обеспечивает вычисление, например сжатие/декомпрессию.

Вам нужно будет написать программу, которая:

  • Загружает zip файл
  • Извлекает файлы
  • Делает ли действия файлы

Это, вероятно, лучше всего сделать на экземпляре Amazon EC2, который будет иметь доступ с низкой задержкой к Amazon S3. Вы можете сделать это с помощью функции AWS Lambda, но она имеет ограничение на 500 МБ дискового хранилища и 5 минут выполнения, что не похоже на вашу ситуацию.

Если вы особенно умны, вы можете загрузить часть каждого zip файла ("ranged get") и интерпретировать заголовок zipfile, чтобы получить список файлов и их размеры, что позволяет избежать загрузки всего файла.

  • 0
    Загрузка начала файла не поможет. Каталоги Zipfile приходят в конце, а не в начале. (Вот как работают эти старые самораспаковывающиеся архивы: вы можете поместить все, что захотите, в начало zipfile, включая PE-заголовок и кучу исполняемого кода, если каталог в конце файла говорит о начале файл игнорируемый мусор.)
  • 0
    Спасибо! Ответ обновлен.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню