2016-02-01 23 views
10

In boto3, esiste un equivalente di get_contents_to_file, che copia il contenuto di un oggetto in un handle di file?Equivale a get_contents_to_file in boto3

In boto, se ho un oggetto S3 key, posso copiare il contenuto in un file temporaneo con:

from tempfile import TemporaryFile 
key = code_that_gets_key() 

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

non ho trovato un equivalente in boto3.

Sono stato in grado di sostituire l'utilizzo di get_contents_to_filename con download_file. Tuttavia, questo copre il caso in cui fornisco il nome del file. In questo caso, voglio fornire l'handle del file come argomento.

Attualmente, posso ottenere il codice per lavorare in boto3 scorrendo sul corpo come segue:

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

Esiste un modo migliore per fare questo in boto3?

+0

Non puoi passare 'tmp_file.name' a' download_file() '? – helloV

+0

@helloV In questo caso potrei usare ['NamedTemporaryFile'] (https://docs.python.org/2/library/tempfile.html#tempfile.NamedTemporaryFile), che ha un nome file. Non sono sicuro che sia una buona idea, dal momento che il metodo 'download_file' aprirà un nuovo handle di file per lo stesso file. In generale, non tutti gli handle di file hanno nomi di file (ad esempio 'StringIO',' TemporaryFile'). – Alasdair

+1

Non è questo ciò che è [download_fileobj] (https://boto3.readthedocs.io/en/latest/reference/services/s3.html#S3.Bucket.download_fileobj)? –

risposta

7

A partire dal V1.4.0 c'è una funzione download_fileobj che fa esattamente quello che vuoi. Come per la documentazione formale:

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

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

L'operazione è disponibile anche sul bucket resource e s3 client così, ad esempio:

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

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

Whoops, dovrebbe essere 's3 = boto3.resource ('s3')'. Mea culpa, i documenti dovrebbero essere aggiornati a breve. Vale anche la pena notare che questa operazione è disponibile sul [client s3] (https://boto3.readthedocs.io/en/latest/reference/services/s3.html#S3.Client.download_fileobj) e [Risorsa oggetto] (https://boto3.readthedocs.io/en/latest/reference/services/s3.html#S3.Object.download_fileobj). –

+0

@JordonPhillips Grazie! Sento che dovrei averlo notato quando ho fatto l'estratto ... –

+0

Grazie Peter e @JordonPhillips. Nel mio caso è stata la versione oggetto che stavo cercando in particolare. – Alasdair

0

La risposta corretta sarebbe quella di utilizzare NamedTemporaryFile invece di TemporaryFile:

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

Ulteriori documenti qui: https://docs.python.org/2/library/tempfile.html

+0

Questo funziona per l'esempio che ho dato, ma non è la soluzione generale che sto cercando. Come ho detto nei commenti, non tutti gli handle di file hanno nomi di file. – Alasdair

0

risposta di Pietro è corretta, ma vorrei sottolineare che attualmente molto di AWS non ha distribuito il boto3 1.4, in particolare AWS Lambda.

Questo non vi impedisce di aggiornare al volo, ma nel caso in cui si sta runing codice su nuove installazioni assicurarsi di controllare che

boto3.__version__ >= '1.4.0' 

e aggiornare la biblioteca, se non. Spero che questo sarà risolto presto e questo sarà discutibile.