Actualmente estoy tratando de cargar un archivo en escabeche de S3 en AWS lambda y almacenarlo en una lista (el encurtido es una lista).
Aquí está mi código:
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)
Recibo el siguiente error a pesar de que el archivo existe:
FileNotFoundError: [Errno 2] No such file or directory: 'oldscreenurls.pkl'
¿Algunas ideas?
solución súper sencilla
import pickle import boto3 s3 = boto3.resource('s3') my_pickle = pickle.loads(s3.Bucket("bucket_name").Object("key_to_pickle.pickle").get()['Body'].read())
Como se muestra en la documentación de download_fileobj
, primero debe abrir el archivo en modo de escritura binaria y guardarlo en el archivo. Una vez descargado el archivo, puede abrirlo para leerlo y descifrarlo.
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
toma el nombre de un objeto en S3 más un identificador en un archivo local y guarda el contenido de ese objeto en el archivo. También hay una versión de esta función llamada download_file
que toma un nombre de archivo en lugar de un identificador de archivo abierto y se encarga de abrirlo por usted.
Sin embargo, en este caso probablemente sería mejor usar S3Client.get_object para evitar tener que escribir y luego leer inmediatamente un archivo. También puede escribir en un objeto BytesIO en memoria, que actúa como un archivo pero en realidad no toca un disco. Eso se vería algo como esto:
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)
Esta es la solución más fácil. Puede cargar los datos sin siquiera descargar el archivo localmente usando S3FileSystem
from s3fs.core import S3FileSystem s3_file = S3FileSystem() data = pickle.load(s3_file.open('{}/{}'.format(bucket_name, file_path)))