from python csv amazon-s3 dataframe boto3

get file from s3 python



Guarde Dataframe en csv directamente en s3 Python (7)

Tengo un DataFrame de pandas que quiero subir a un nuevo archivo CSV. El problema es que no quiero guardar el archivo localmente antes de transferirlo a s3. ¿Hay algún método como to_csv para escribir el marco de datos en s3 directamente? Estoy usando boto3.
Esto es lo que tengo hasta ahora:

import boto3 s3 = boto3.client(''s3'', aws_access_key_id=''key'', aws_secret_access_key=''secret_key'') read_file = s3.get_object(Bucket, Key) df = pd.read_csv(read_file[''Body'']) # Make alterations to DataFrame # Then export DataFrame to CSV through direct transfer to s3


Esta es una respuesta más actualizada:

import s3fs s3 = s3fs.S3FileSystem(anon=False) # Use ''w'' for py3, ''wb'' for py2 with s3.open(''<bucket-name>/<filename>.csv'',''w'') as f: df.to_csv(f)

El problema con StringIO es que va a acabar con tu memoria. Con este método, está transmitiendo el archivo a s3, en lugar de convertirlo en cadena, luego escribiéndolo en s3. Mantener el marco de datos de pandas y su copia de cadena en la memoria parece muy ineficiente.

Si está trabajando en un instante ec2, puede asignarle un rol de IAM para que pueda escribirlo en s3, por lo que no necesita pasar las credenciales directamente. Sin embargo, también puede conectarse a un depósito pasando credenciales a la función S3FileSystem() . Ver documentación: https://s3fs.readthedocs.io/en/latest/


Leí un csv con dos columnas del cubo s3, y el contenido del archivo csv lo puse en el marco de datos de pandas.

Ejemplo:

config.json

{ "credential": { "access_key":"xxxxxx", "secret_key":"xxxxxx" } , "s3":{ "bucket":"mybucket", "key":"csv/user.csv" } }

cls_config.json

#!/usr/bin/env python # -*- coding: utf-8 -*- import os import json class cls_config(object): def __init__(self,filename): self.filename = filename def getConfig(self): fileName = os.path.join(os.path.dirname(__file__), self.filename) with open(fileName) as f: config = json.load(f) return config

cls_pandas.py

#!/usr/bin/env python # -*- coding: utf-8 -*- import pandas as pd import io class cls_pandas(object): def __init__(self): pass def read(self,stream): df = pd.read_csv(io.StringIO(stream), sep = ",") return df

cls_s3.py

#!/usr/bin/env python # -*- coding: utf-8 -*- import boto3 import json class cls_s3(object): def __init__(self,access_key,secret_key): self.s3 = boto3.client(''s3'', aws_access_key_id=access_key, aws_secret_access_key=secret_key) def getObject(self,bucket,key): read_file = self.s3.get_object(Bucket=bucket, Key=key) body = read_file[''Body''].read().decode(''utf-8'') return body

prueba.py

#!/usr/bin/env python # -*- coding: utf-8 -*- from cls_config import * from cls_s3 import * from cls_pandas import * class test(object): def __init__(self): self.conf = cls_config(''config.json'') def process(self): conf = self.conf.getConfig() bucket = conf[''s3''][''bucket''] key = conf[''s3''][''key''] access_key = conf[''credential''][''access_key''] secret_key = conf[''credential''][''secret_key''] s3 = cls_s3(access_key,secret_key) ob = s3.getObject(bucket,key) pa = cls_pandas() df = pa.read(ob) print df if __name__ == ''__main__'': test = test() test.process()


Me gusta s3fs que te permite usar s3 (casi) como un sistema de archivos local.

Puedes hacerlo:

import s3fs bytes_to_write = df.to_csv(None).encode() fs = s3fs.S3FileSystem(key=key, secret=secret) with fs.open(''s3://bucket/path/to/file.csv'', ''wb'') as f: f.write(bytes_to_write)

s3fs solo wb modos rb y wb para abrir el archivo, es por eso que hice esto de bytes_to_write .


Puede usar directamente la ruta S3. Estoy usando Pandas 0.24.1

In [1]: import pandas as pd In [2]: df = pd.DataFrame( [ [1, 1, 1], [2, 2, 2] ], columns=[''a'', ''b'', ''c'']) In [3]: df Out[3]: a b c 0 1 1 1 1 2 2 2 In [4]: df.to_csv(''s3://experimental/playground/temp_csv/dummy.csv'', index=False) In [5]: pd.__version__ Out[5]: ''0.24.1'' In [6]: new_df = pd.read_csv(''s3://experimental/playground/temp_csv/dummy.csv'') In [7]: new_df Out[7]: a b c 0 1 1 1 1 2 2 2

Nota de lanzamiento:

Manejo de archivos S3

pandas ahora usa s3fs para manejar conexiones S3. Esto no debería romper ningún código. Sin embargo, dado que s3fs no es una dependencia requerida, deberá instalarlo por separado, como boto en versiones anteriores de pandas. GH11915 .


Puedes usar:

from io import StringIO # python3; python2: BytesIO import boto3 csv_buffer = StringIO() df.to_csv(csv_buffer) s3_resource = boto3.resource(''s3'') s3_resource.Object(bucket, ''df.csv'').put(Body=csv_buffer.getvalue())


Si pasa None como el primer argumento para to_csv() los datos se devolverán como una cadena. A partir de ahí, es un paso fácil subir eso a S3 de una vez.

También debería ser posible pasar un objeto StringIO a to_csv() , pero usar una cadena será más fácil.


import boto3 s3_client = boto3.client(''s3'',aws_access_key_id="AccessKey",aws_secret_access_key="Secretkey") head_response = s3_client.head_object(Bucket=''YourBucket'',Key=''YourPath'') if head_response[''HTTPStatusCode''] == 200: Your operation if file exsits