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.

158voto

Stefan Points 19063

pandas utilise boto pour read_csv donc vous devriez pouvoir le faire :

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

Si vous avez besoin boto3 parce que vous êtes sur python3.4+ vous pouvez

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()))

Depuis version 0.20.1 pandas utilise s3fs voir la réponse ci-dessous.

0 votes

Existe-t-il un moyen d'utiliser une URL sans la rendre publique pour tout le monde ? Le fichier doit rester privé.

0 votes

Le site boto3 montre comment configurer l'authentification de manière à ce que vous puissiez également accéder aux fichiers privés : boto3.readthedocs.io/fr/latest/guide/quickstart.html

1 votes

Il jette NoCredentialsError. Comment puis-je définir les informations d'identification s3 ? Je suis nouveau dans le monde de Python et de Boto.

113voto

Wesam Points 768

Maintenant pandas peut gérer les URLs S3 . Vous pourriez simplement le faire :

import pandas as pd
import s3fs

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

Vous devez installer s3fs si vous ne l'avez pas. pip install s3fs

Authentification

Si votre seau S3 est privé et nécessite une authentification, vous avez deux options :

1- Ajouter les informations d'accès à votre ~/.aws/credentials fichier de configuration

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

Ou

2- Régler les éléments suivants variables d'environnement avec leurs valeurs appropriées :

  • aws_access_key_id
  • aws_secret_access_key
  • aws_session_token

1 votes

Magnifique. Fonctionne en python3.

0 votes

et l'authentification ?

2 votes

@JamesWierzba , j'ai ajouté plus de détails sur l'authentification à ma réponse ci-dessus.

21voto

Cette fonction est désormais prise en charge par la dernière version de pandas. Voir

http://pandas.pydata.org/pandas-docs/stable/io.html#reading-remote-files

eg.,

df = pd.read_csv('s3://pandas-test/tips.csv')

18voto

Ricardo Mutti Points 704

Pour python 3.6+, Amazon dispose maintenant d'une très belle bibliothèque pour utiliser Pandas avec ses services, appelée awswrangler .

import awswrangler as wr
import boto3

# Boto3 session
session = boto3.session.Session(aws_access_key_id='XXXX', 
                                aws_secret_access_key='XXXX')

# Awswrangler pass forward all pd.read_csv() function args
df = wr.s3.read_csv(path='s3://bucket/path/',
                    boto3_session=session,
                    skiprows=2,
                    sep=';',
                    decimal=',',
                    na_values=['--'])

Pour installer awswrangler : pip install awswrangler

13voto

Dror Points 953

Avec s3fs il peut être fait comme suit :

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)

2 votes

Je pense qu'avec s3fs tu peux même écrire df = pd.read_csv('s3://mybucket/path/to/object/foo.pkl')

1 votes

@louis_guitton cela semble fonctionner avec pd-read_csv mais pas avec read_pickle

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