2016-02-01 7 views
10

Gibt es in boto3 ein Äquivalent von get_contents_to_file, das den Inhalt eines Objekts in ein Datei-Handle kopiert?Entspricht get_contents_to_file in boto3

In Boto, wenn ich ein S3-Objekt key habe, kann ich den Inhalt in eine temporäre Datei kopieren mit:

from tempfile import TemporaryFile 
key = code_that_gets_key() 

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

Ich habe kein Äquivalent in boto3 gefunden.

Ich konnte die Verwendung von get_contents_to_filename durch download_file ersetzen. Dies deckt jedoch den Fall ab, in dem ich den Dateinamen zur Verfügung stelle. In diesem Fall möchte ich das Dateihandle als Argument bereitstellen.

Derzeit kann ich den Code bekommen in boto3 zu arbeiten, indem sie über den Körper laufen wie folgt:

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

Gibt es einen besseren Weg, dies in boto3 zu tun?

+0

Können Sie 'tmp_file.name' nicht an' download_file() 'übergeben? – helloV

+0

@helloV In diesem Fall könnte ich ['NamedTemporaryFile'] (https://docs.python.org/2/library/tempfile.html#tempfile.NamedTemporaryFile) verwenden, das einen Dateinamen hat. Ich bin mir nicht sicher, ob das eine gute Idee ist, da die 'download_file'-Methode ein neues Datei-Handle für dieselbe Datei öffnet. Im Allgemeinen haben nicht alle Dateizugriffsnummern Dateinamen (z. B. "StringIO", "TemporaryFile"). – Alasdair

+1

Ist das nicht das, was [download_fileobj] (https://boto3.readthedocs.io/en/latest/reference/services/s3.html#S3.Bucket.download_fileobj) ist? –

Antwort

7

Ab V1.4.0 gibt es eine download_fileobj Funktion, die genau das tut, was Sie wollen. Gemäß der formalen Dokumentation:

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

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

Der Betrieb ist auch auf den bucket resource und s3 client als auch, zum Beispiel:

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

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

Whoops, das sollte 's3 = boto3.resource ('s3')' sein. Mea culpa, die Dokumentation sollte in Kürze aktualisiert werden. Es ist auch erwähnenswert, dass diese Operation auf dem [s3-Client] (https://boto3.readthedocs.io/de/latest/reference/services/s3.html#S3.Client.download_fileobj) und [Objektressource] verfügbar ist. (https://boto3.readthedocs.io/en/latest/reference/services/s3.html#S3.Object.download_fileobj). –

+0

@JordonPhillips Danke! Ich denke, ich hätte das beim Ausschneiden sehen sollen ... –

+0

Danke Peter und @JordonPhillips. In meinem Fall war es die Objektversion, die ich gezielt suchte. – Alasdair

0

Die richtige Antwort wäre NamedTemporaryFile zu verwenden, anstatt TemporaryFile:

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

More docs hier: https://docs.python.org/2/library/tempfile.html

+0

Dies funktioniert für das Beispiel, das ich gab, aber es ist nicht die allgemeine Lösung, nach der ich suche. Wie ich in den Kommentaren gesagt habe, haben nicht alle Datei-Handles Dateinamen. – Alasdair

0

Peters Antwort ist richtig, aber ich würde die gerne noch viel beachten von AWS hat nicht Boto3 1.4 im Einsatz, vor allem AWS Lambda.

wenn nicht in Fall überprüfen Sie runing Code auf Neuinstallationen sicherstellen, dass

boto3.__version__ >= '1.4.0' 

und die Bibliothek aktualisiert Dies verhindert nicht im laufenden Betrieb von der Aktualisierung, aber. Hoffentlich wird dies bald behoben und dies wird strittig sein.