127 votes

Comment importer un fichier texte sur AWS S3 dans pandas sans écrire sur le disque ?

J'ai un fichier texte enregistré sur S3 qui est un tableau délimité par des tabulations. Je veux le charger dans pandas mais je ne peux pas l'enregistrer d'abord parce que je fonctionne sur un serveur heroku. Voici ce que j'ai jusqu'à présent.

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)

l'erreur est

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

Comment puis-je convertir le corps de la réponse dans un format que pandas acceptera ?

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

MISE À JOUR - L'utilisation de ce qui suit a fonctionné

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

et

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

0 votes

Essayez de cette façon : io.BytesIO(file) ou io.StringIO(file) au lieu de file dans le read_csv() appelez

0 votes

Vous pourriez utiliser io.StringIO dans le cas de cette réponse .

0 votes

Aucune de ces suggestions n'a fonctionné. Vous pouvez voir les erreurs dans mon post edit.

3voto

aviral sanjay Points 25

Comme les fichiers peuvent être trop volumineux, il n'est pas judicieux de les charger tous dans le dataframe. Il faut donc les lire ligne par ligne et les enregistrer dans le dataframe. Oui, nous pouvons également fournir la taille des morceaux dans le read_csv mais nous devons alors gérer le nombre de lignes lues.

D'où l'idée de cette ingénierie :

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=",")

Je supprime également le df une fois le travail terminé. del df

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