Эквивалентно get_contents_to_file в boto3

В boto3 существует ли эквивалент get_contents_to_file, который копирует содержимое объекта в дескриптор файла?

В boto, если у меня есть объект S3 key, я могу скопировать содержимое во временный файл с помощью
from tempfile import TemporaryFile
key = code_that_gets_key()

with TemporaryFile() as tmp_file:
    key.get_contents_to_file(key, tmpfile)

Я не нашел эквивалент в boto3.

Мне удалось заменить использование get_contents_to_filename с download_file. Однако это касается случая, когда я предоставляю имя файла. В этом случае я хочу предоставить дескриптор файла в качестве аргумента.

В настоящее время я могу заставить код работать в boto3, итерации по телу следующим образом:

with TemporaryFile() as tmp_file:
    body = key.get()['Body']
    for chunk in iter(lambda: body.read(4096), b''):
        filehandle.write(chunk)

Есть ли лучший способ сделать это в boto3?

Ответ 1

В V1.4.0 есть download_fileobj, которая делает именно то, что вы хотите. Согласно официальной документации:

import boto3
s3 = boto3.resource('s3')
bucket = s3.Bucket('mybucket')
obj = bucket.Object('mykey')

with open('filename', 'wb') as data:
    obj.download_fileobj(data)

Операция также доступна в ресурсе bucket и s3 client, например:

import boto3
s3 = boto3.resource('s3')
bucket = s3.Bucket('mybucket')

with open('filename', 'wb') as data:
    bucket.download_fileobj('mykey', data)

Ответ 2

Правильным ответом будет использование NamedTemporaryFile вместо TemporaryFile:

with NamedTemporaryFile() as tmp_file:
    file_name = tmp_file.name # This is what you are looking for

Больше документов здесь: https://docs.python.org/2/library/tempfile.html

Ответ 3

Ответ Питера правильный, но я хотел бы отметить, что в настоящее время большая часть AWS не имеет развернутого boto3 1.4, в первую очередь AWS Lambda.

Это не мешает вам обновляться "на лету", но если вы запускаете код на свежих установках, убедитесь, что

boto3.__version__ >= '1.4.0'

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