206 votes

Comment écrire un fichier ou des données dans un objet S3 en utilisant boto3

Dans le boto 2, vous pouvez écrire dans un objet S3 en utilisant ces méthodes :

Existe-t-il un équivalent du boto 3 ? Quelle est la méthode boto3 pour sauvegarder des données dans un objet stocké sur S3 ?

383voto

jkdev Points 930

Dans le boto 3, les méthodes "Key.set_contents_from_" ont été remplacées par les méthodes suivantes

Par exemple :

import boto3

some_binary_data = b'Here we have some data'
more_binary_data = b'Here we have some more data'

# Method 1: Object.put()
s3 = boto3.resource('s3')
object = s3.Object('my_bucket_name', 'my/key/including/filename.txt')
object.put(Body=some_binary_data)

# Method 2: Client.put_object()
client = boto3.client('s3')
client.put_object(Body=more_binary_data, Bucket='my_bucket_name', Key='my/key/including/anotherfilename.txt')

Alternativement, les données binaires peuvent provenir de la lecture d'un fichier, comme décrit dans la rubrique les docs officiels comparant boto 2 et boto 3 :

Stockage des données

Il est facile de stocker des données à partir d'un fichier, d'un flux ou d'une chaîne :

# Boto 2.x
from boto.s3.key import Key
key = Key('hello.txt')
key.set_contents_from_file('/tmp/hello.txt')

# Boto 3
s3.Object('mybucket', 'hello.txt').put(Body=open('/tmp/hello.txt', 'rb'))

0 votes

Botocore.exceptions.NoCredentialsError : Impossible de localiser les informations d'identification. Comment résoudre ce problème ?

2 votes

@deepakmurthy Je ne sais pas pourquoi vous obtenez cette erreur... Vous devez poser une nouvelle question sur Stack Overflow et fournir plus de détails sur le problème.

2 votes

Quand j'essaie s3.Object().put() Je me retrouve avec un objet avec zéro content-length . Pour moi put() n'accepte que les données de type chaîne, mais put(str(binarydata)) semble avoir des problèmes d'encodage. Je me retrouve avec un objet qui fait environ trois fois la taille des données d'origine, ce qui le rend inutile pour moi.

103voto

EM Bee Points 305

Boto3 dispose également d'une méthode pour télécharger directement un fichier :

s3 = boto3.resource('s3')    
s3.Bucket('bucketname').upload_file('/local/file/here.txt','folder/sub/path/to/s3key')

http://boto3.readthedocs.io/en/latest/reference/services/s3.html#S3.Bucket.upload_file

16 votes

C'est bien, mais cela ne permet pas de stocker les données actuellement en mémoire.

20 votes

@Reid : pour les fichiers en mémoire, vous pouvez utiliser la fonction s3.Bucket(...).upload_fileobj() à la place.

3 votes

Comment se comporte l'écriture à partir de la mémoire par rapport au téléchargement vers s3 à partir d'un fichier écrit localement ?

75voto

Franke Points 161

Vous n'avez plus besoin de convertir le contenu en binaire avant d'écrire dans le fichier dans S3. L'exemple suivant crée un nouveau fichier texte (appelé newfile.txt) dans un seau S3 avec un contenu de chaîne de caractères :

import boto3

s3 = boto3.resource(
    's3',
    region_name='us-east-1',
    aws_access_key_id=KEY_ID,
    aws_secret_access_key=ACCESS_KEY
)
content="String content to write to a new S3 file"
s3.Object('my-bucket-name', 'newfile.txt').put(Body=content)

0 votes

Je n'ai aucune idée que mon action "put" n'a pas d'accès. J'ai créé ce seau et mis mon identifiant canonique dans la liste d'accès.

0 votes

Comment donner à un prefix dans ce cas ? En d'autres termes, que se passe-t-il si vous voulez stocker le fichier en my-bucket-name/subfolder/ ?

4 votes

@kev vous pouvez spécifier cela avec le nom de fichier 'sous-dossier/newfile.txt' au lieu de 'newfile.txt'.

47voto

Uri Goren Points 445

Voici une belle astuce pour lire JSON depuis s3 :

import json, boto3
s3 = boto3.resource("s3").Bucket("bucket")
json.load_s3 = lambda f: json.load(s3.Object(key=f).get()["Body"])
json.dump_s3 = lambda obj, f: s3.Object(key=f).put(Body=json.dumps(obj))

Vous pouvez maintenant utiliser json.load_s3 y json.dump_s3 avec la même API que load y dump

data = {"test":0}
json.dump_s3(data, "key") # saves json to s3://bucket/key
data = json.load_s3("key") # read json from s3://bucket/key

4 votes

Excellent. Pour que ça marche, j'ai ajouté ce petit extra : ...["Body"].read().decode('utf-8') .

0 votes

Excellente idée. Quoi qu'il en soit, cela laisse un peu de place pour l'amélioration des noms.

1 votes

Proposition de réécriture de cette belle idée : gist.github.com/vlcinsky/bbeda4321208aa98745afc29b58e90ac

32voto

kev Points 1376

Une version plus propre et concise que j'utilise pour télécharger des fichiers à la volée vers un seau S3 et un sous-dossier donnés

import boto3

BUCKET_NAME = 'sample_bucket_name'
PREFIX = 'sub-folder/'

s3 = boto3.resource('s3')

# Creating an empty file called "_DONE" and putting it in the S3 bucket
s3.Object(BUCKET_NAME, PREFIX + '_DONE').put(Body="")

Note _: Vous devez TOUJOURS mettre vos informations d'identification AWS ( aws_access_key_id y aws_secret_access_key ) dans un fichier séparé, par exemple- ~/.aws/credentials_

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X