que para aws python pandas heroku amazon-s3 boto3

python - para - que es boto3



Cómo importar un archivo de texto en AWS S3 en pandas sin escribir en el disco (6)

Tengo un archivo de texto guardado en S3 que es una tabla delimitada por tabulaciones. Quiero cargarlo en pandas pero no puedo guardarlo primero porque lo estoy ejecutando en un servidor heroku. Esto es lo que tengo hasta ahora.

import io import boto3 import os import pandas as pd os.environ["AWS_ACCESS_KEY_ID"] = "xxxxxxxx" os.environ["AWS_SECRET_ACCESS_KEY"] = "xxxxxxxx" s3_client = boto3.client(''s3'') response = s3_client.get_object(Bucket="my_bucket",Key="filename.txt") file = response["Body"] pd.read_csv(file, header=14, delimiter="/t", low_memory=False)

el error es

OSError: Expected file path name or file-like object, got <class ''bytes''> type

¿Cómo convierto el cuerpo de respuesta en un formato que los pandas aceptarán?

pd.read_csv(io.StringIO(file), header=14, delimiter="/t", low_memory=False) returns TypeError: initial_value must be str or None, not StreamingBody pd.read_csv(io.BytesIO(file), header=14, delimiter="/t", low_memory=False) returns TypeError: ''StreamingBody'' does not support the buffer interface

ACTUALIZACIÓN - Usando el siguiente trabajo

file = response["Body"].read()

y

pd.read_csv(io.BytesIO(file), header=14, delimiter="/t", low_memory=False)


Ahora los pandas pueden manejar URL S3 . Simplemente podrías hacer:

import pandas as pd import s3fs df = pd.read_csv(''s3://bucket-name/file.csv'')

Necesita instalar s3fs si no lo tiene. pip install s3fs

Autenticación

Si su depósito S3 es privado y requiere autenticación, tiene dos opciones:

1- Agregue credenciales de acceso a su archivo de configuración ~/.aws/credentials

[default] aws_access_key_id=AKIAIOSFODNN7EXAMPLE aws_secret_access_key=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY

O

2- Establezca las siguientes variables de entorno con sus valores adecuados:

  • aws_access_key_id
  • aws_secret_access_key
  • aws_session_token

Como los archivos pueden ser demasiado grandes, no es aconsejable cargarlos en el marco de datos por completo. Por lo tanto, lea línea por línea y guárdelo en el marco de datos. Sí, también podemos proporcionar el tamaño del fragmento en read_csv, pero luego tenemos que mantener el número de filas leídas.

Por lo tanto, se me ocurrió esta ingeniería:

def create_file_object_for_streaming(self): print("creating file object for streaming") self.file_object = self.bucket.Object(key=self.package_s3_key) print("File object is: " + str(self.file_object)) print("Object file created.") return self.file_object for row in codecs.getreader(self.encoding)(self.response[u''Body'']).readlines(): row_string = StringIO(row) df = pd.read_csv(row_string, sep=",")

También elimino el df una vez que el trabajo está hecho. del df


Con s3fs se puede hacer de la siguiente manera:

import s3fs import pandas as pd fs = s3fs.S3FileSystem(anon=False) # CSV with fs.open(''mybucket/path/to/object/foo.pkl'') as f: df = pd.read_csv(f) # Pickle with fs.open(''mybucket/path/to/object/foo.pkl'') as f: df = pd.read_pickle(f)



Una opción es convertir el csv a json a través de df.to_dict() y luego almacenarlo como una cadena. Tenga en cuenta que esto solo es relevante si el CSV no es un requisito, pero solo desea colocar rápidamente el marco de datos en un depósito S3 y recuperarlo nuevamente.

from boto.s3.connection import S3Connection import pandas as pd import yaml conn = S3Connection() mybucket = conn.get_bucket(''mybucketName'') myKey = mybucket.get_key("myKeyName") myKey.set_contents_from_string(str(df.to_dict()))

Esto convertirá el df en una cadena dict, y luego lo guardará como json en S3. Más tarde puede leerlo en el mismo formato json:

df = pd.DataFrame(yaml.load(myKey.get_contents_as_string()))

Las otras soluciones también son buenas, pero esto es un poco más simple. Puede que no se requiera necesariamente Yaml, pero necesita algo para analizar la cadena json. Si el archivo S3 no necesariamente necesita ser un CSV, esto puede ser una solución rápida.


pandas usa boto para read_csv , por lo que debería poder:

import boto data = pd.read_csv(''s3://bucket....csv'')

Si necesita boto3 porque está en python3.4+ , puede

import boto3 import io s3 = boto3.client(''s3'') obj = s3.get_object(Bucket=''bucket'', Key=''key'') df = pd.read_csv(io.BytesIO(obj[''Body''].read()))