web-dev-qa-db-fra.com

Comment charger un fichier pickle depuis S3 pour l'utiliser dans AWS Lambda?

J'essaie actuellement de charger un fichier mariné de S3 dans AWS lambda et de le stocker dans une liste (le cornichon est une liste).

Voici mon code:

import pickle
import boto3

s3 = boto3.resource('s3')
with open('oldscreenurls.pkl', 'rb') as data:
    old_list = s3.Bucket("pythonpickles").download_fileobj("oldscreenurls.pkl", data)

J'obtiens l'erreur suivante même si le fichier existe:

FileNotFoundError: [Errno 2] No such file or directory: 'oldscreenurls.pkl'

Des idées?

10
mifin

Comme indiqué dans la documentation de download_fileobj , vous devez ouvrir le fichier en mode binaire écrire et l'enregistrer d'abord dans le fichier. Une fois le fichier téléchargé, vous pouvez l'ouvrir pour le lire et le décaper.

import pickle
import boto3

s3 = boto3.resource('s3')
with open('oldscreenurls.pkl', 'wb') as data:
    s3.Bucket("pythonpickles").download_fileobj("oldscreenurls.pkl", data)

with open('oldscreenurls.pkl', 'rb') as data:
    old_list = pickle.load(data)

download_fileobj prend le nom d'un objet dans S3 plus une poignée dans un fichier local et enregistre le contenu de cet objet dans le fichier. Il existe également une version de cette fonction appelée download_file qui prend un nom de fichier au lieu d'un descripteur de fichier ouvert et gère son ouverture pour vous.

Dans ce cas, il serait probablement préférable d'utiliser S3Client.get_object pour éviter d'avoir à écrire puis à lire immédiatement un fichier. Vous pouvez également écrire sur un objet BytesIO en mémoire, qui agit comme un fichier mais ne touche pas réellement un disque. Cela ressemblerait à quelque chose comme ceci:

import pickle
import boto3
from io import BytesIO

s3 = boto3.resource('s3')
with BytesIO() as data:
    s3.Bucket("pythonpickles").download_fileobj("oldscreenurls.pkl", data)
    data.seek(0)    # move back to the beginning after writing
    old_list = pickle.load(data)
8
avigil

Solution super simple

import pickle
import boto3

s3 = boto3.resource('s3')
my_pickle = pickle.loads(s3.Bucket("bucket_name").Object("key_to_pickle.pickle").get()['Body'].read())
8
kindjacket