Поток большой строки на S3, используя boto3 - PullRequest
0 голосов
/ 16 октября 2018

Я загружаю файлы с S3, преобразовываю данные внутри них, а затем создаю новый файл для загрузки на S3.Файлы, которые я загружаю, имеют размер менее 2 ГБ, но из-за того, что я расширяю данные, когда я их загружаю, они довольно большие (200 ГБ +).

В настоящее время вы можете представить себе, что код выглядит так:

files = list_files_in_s3()
new_file = open('new_file','w')
for file in files:
    file_data = fetch_object_from_s3(file)
    str_out = ''
    for data in file_data:
        str_out += transform_data(data)
    new_file.write(str_out)
s3.upload_file('new_file', 'bucket', 'key')

Проблема в том, что new_file слишком велик, чтобы иногда помещаться на диск.Из-за этого я хочу использовать boto3 upload_fileobj для загрузки данных в потоковой форме, чтобы мне вообще не нужно было располагать временный файл на диске.

Может ли кто-нибудь помочь привести пример этого?Кажется, метод Python сильно отличается от Java, с которым я знаком.

1 Ответ

0 голосов
/ 17 октября 2018

Вы можете использовать параметр amt в функции чтения, задокументированной здесь: https://botocore.amazonaws.com/v1/documentation/api/latest/reference/response.html.

А затем использовать описанную здесь MultiPartUpload, чтобы загрузить файл по частям: https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/s3.html#multipartupload

https://docs.aws.amazon.com/AmazonS3/latest/dev/mpuoverview.html

У вас должно быть правило, которое удаляет неполные многокомпонентные загрузки:

https://aws.amazon.com/es/blogs/aws/s3-lifecycle-management-update-support-for-multipart-uploads-and-delete-markers/

, иначе вы можете заплатить за неполные сохраненные части данныхв S3.

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

Вам все равно придется использовать MultiPartUpload, поскольку у S3 есть ограничения на размер файлов, которые вы можете загрузить за одно действие: https://aws.amazon.com/s3/faqs/

"Самый большой объект, который может быть загружен в одном PUT, составляет 5 гигабайт. Для объектов размером более 100 мегабайт клиентам следует рассмотреть возможность использования многочастной загрузки."

Это пример кода (я не проверялэтот код как здесь):

import boto3
amt = 1024*1024*10 # 10 MB at the time
session = boto3.Session(profile_name='yourprofile')
s3res = session.resource('s3')
source_s3file = "yourfile.file"
target_s3file = "yourfile.file"
source_s3obj = s3res.Object("your-bucket", source_s3file)
target_s3obj = s3res.Object("your-bucket", target_s3file)

# initiate MultiPartUpload
mpu = target_s3obj.initiate_multipart_upload()
partNr = 0
parts = []

body = source_s3obj.get()["Body"]   
# get initial chunk
chunk = body.read(amt=amt).decode("utf-8") # this is where you use the amt-parameter
# Every time you call the read-function it reads the next chunk of data until its empty.
# Then do something with the chunk and upload it to S3 using MultiPartUpload
partNr += 1
part = mpu.Part(partNr)
response = part.upload(Body=f)
parts.append({
    "PartNumber": partNr,
    "ETag": response["ETag"]
})

while len(chunk) > 0:
    # there is more data, get a new chunk
    chunk = body.read(amt=amt).decode("utf-8")
    # do something with the chunk, and upload the part
    partNr += 1
    part = mpu.Part(partNr)
    response = part.upload(Body=f)
    parts.append({
        "PartNumber": partNr,
        "ETag": response["ETag"]
    })
# no more chunks, complete the upload
part_info = {}
part_info["Parts"] = parts
mpu_result = mpu.complete(MultipartUpload=part_info)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...