2015-03-31 5 views
83

Я пытаюсь сделать «привет мир» с новым клиентом boto3 для AWS.Как сохранить объект S3 в файл с помощью boto3

Использование прецедента у меня довольно просто: получить объект из S3 и сохранить его в файле.

В Boto 2.X я хотел бы сделать это следующим образом:

import boto 
key = boto.connect_s3().get_bucket('foo').get_key('foo') 
key.get_contents_to_filename('/tmp/foo') 

В Бото 3. Я не могу найти чистый способ сделать то же самое, так что я вручную итерацию над объектом «Streaming»:

import boto3 
key = boto3.resource('s3').Object('fooo', 'docker/my-image.tar.gz').get() 
with open('/tmp/my-image.tar.gz', 'w') as f: 
    chunk = key['Body'].read(1024*8) 
    while chunk: 
     f.write(chunk) 
     chunk = key['Body'].read(1024*8) 

или

import boto3 
key = boto3.resource('s3').Object('fooo', 'docker/my-image.tar.gz').get() 
with open('/tmp/my-image.tar.gz', 'w') as f: 
    for chunk in iter(lambda: key['Body'].read(4096), b''): 
     f.write(chunk) 

И это прекрасно работает. Мне было интересно, есть ли какая-нибудь «родная» функция boto3, которая будет выполнять ту же задачу?

ответ

139

Существует настройка, которая недавно входила в Boto3, которая помогает в этом (между прочим). В настоящее время она подвергается на S3 клиента низкого уровня, и может быть использован, как это:

s3_client = boto3.client('s3') 
open('hello.txt').write('Hello, world!') 

# Upload the file to S3 
s3_client.upload_file('hello.txt', 'MyBucket', 'hello-remote.txt') 

# Download the file from S3 
s3_client.download_file('MyBucket', 'hello-remote.txt', 'hello2.txt') 
print(open('hello2.txt').read()) 

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

+1

@Daniel: Спасибо за Ваш ответ. Можете ли вы ответить на ответ, если я хочу загрузить файл, используя multipart upload в boto3. –

+1

@RahulKumarPatle метод 'upload_file' автоматически будет использовать многостраничные загрузки для больших файлов. – Daniel

+0

@ Daniel - Что касается multipart_upload, я создал [SO question] (http://stackoverflow.com/questions/34303775/complete-a-multipart-upload-with-boto3). Метод 'upload_file', как представляется, автоматически не использует многостраничную загрузку для размеров файлов, превышающих конфигурацию' multipart_threshold'; по крайней мере, я не смог заставить его работать таким образом. Я хотел бы ошибаться! Любая помощь приветствуется. – blehman

43

boto3 теперь имеет более приятный интерфейс, чем клиент:

resource = boto3.resource('s3') 
my_bucket = resource.Bucket('MyBucket') 
my_bucket.download_file(key, local_filename) 

Это само по себе не является чрезвычайно лучше, чем client в принятом ответ (хотя документы говорят, что он делает лучше работу загрузки и повторной попыткой загрузка с ошибкой), но учитывая, что ресурсы, как правило, более эргономичны (например, ресурсы s3 bucket и object более приятны, чем клиентские), это позволяет вам оставаться на уровне ресурсов без необходимости раскрываться.

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

+1

Я использую это плавно. Благодарю. – arsho

+1

Отличный пример и добавление, поскольку исходный вопрос задает вопрос о сохранении объекта, соответствующий метод здесь - 'my_bucket.upload_file()' (или 'my_bucket.upload_fileobj()', если у вас есть объект BytesIO). – SMX

31

Для тех из вас, кто хотел бы, чтобы имитировать set_contents_from_string как методы boto2, вы можете попробовать

import boto3 
from cStringIO import StringIO 

s3c = boto3.client('s3') 
contents = 'My string to save to S3 object' 
target_bucket = 'hello-world.by.vor' 
target_file = 'data/hello.txt' 
fake_handle = StringIO(contents) 

# notice if you do fake_handle.read() it reads like a file handle 
s3c.put_object(Bucket=target_bucket, Key=target_file, Body=fake_handle.read()) 
+12

Вот и ответ. Вот вопрос: «Как сохранить строку для объекта S3 с помощью boto3?» – jkdev

+0

для python3 Мне пришлось использовать import io; fake_handl e = io.StringIO (содержимое) – Felix

5
# Preface: File is json with contents: {'name': 'Android', 'status': 'ERROR'} 

import boto3 
import io 

s3 = boto3.resource(
    's3', 
    aws_access_key_id='my_access_id', 
    aws_secret_access_key='my_secret_key' 
) 

obj = s3.Object('my-bucket', 'key-to-file.json') 
data = io.BytesIO() 
obj.download_fileobj(data) 

# object is now a bytes string, Converting it to a dict: 
new_dict = json.loads(data.getvalue().decode("utf-8")) 

print(new_dict['status']) 
# Should print "Error" 
+8

Никогда не помещайте свой AWS_ACCESS_KEY_ID или ваш AWS_SECRET_ACCESS_KEY в свой код. Они должны быть определены командой awscli 'aws configure', и они будут автоматически найдены' botocore'. –

+0

Действительная точка. Должен был включить это на самом деле. – SixDays