web-dev-qa-db-fra.com

Comment lire un fichier csv à partir d'un compartiment s3 en utilisant Pandas in Python

J'essaie de lire un fichier CSV situé dans un compartiment AWS S3 en mémoire en tant que pandas dataframe en utilisant le code suivant:

import pandas as pd
import boto

data = pd.read_csv('s3:/example_bucket.s3-website-ap-southeast-2.amazonaws.com/data_1.csv')

Afin de donner un accès complet, j'ai défini la stratégie de compartiment sur le compartiment S3 comme suit:

{
"Version": "2012-10-17",
"Id": "statement1",
"Statement": [
    {
        "Sid": "statement1",
        "Effect": "Allow",
        "Principal": "*",
        "Action": "s3:*",
        "Resource": "arn:aws:s3:::example_bucket"
    }
]

}

Malheureusement, j'obtiens toujours l'erreur suivante en python:

boto.exception.S3ResponseError: S3ResponseError: 405 Method Not Allowed

Vous vous demandez si quelqu'un pourrait aider à expliquer comment définir correctement les autorisations dans AWS S3 ou configurer correctement pandas pour importer le fichier. Merci!

9
Paul_M

Utilisation de pandas 0.20.3

import os
import boto3
import pandas as pd
import sys

if sys.version_info[0] < 3: 
    from StringIO import StringIO # Python 2.x
else:
    from io import StringIO # Python 3.x

# get your credentials from environment variables
aws_id = os.environ['AWS_ID']
aws_secret = os.environ['AWS_SECRET']

client = boto3.client('s3', aws_access_key_id=aws_id,
        aws_secret_access_key=aws_secret)

bucket_name = 'my_bucket'

object_key = 'my_file.csv'
csv_obj = client.get_object(Bucket=bucket_name, Key=object_key)
body = csv_obj['Body']
csv_string = body.read().decode('utf-8')

df = pd.read_csv(StringIO(csv_string))
19
jpobst

Vous n'avez pas besoin de pandas .. vous pouvez simplement utiliser la bibliothèque csv par défaut de python

def read_file(bucket_name,region, remote_file_name, aws_access_key_id, aws_secret_access_key):
    # reads a csv from AWS

    # first you stablish connection with your passwords and region id

    conn = boto.s3.connect_to_region(
        region,
        aws_access_key_id=aws_access_key_id,
        aws_secret_access_key=aws_secret_access_key)

    # next you obtain the key of the csv you want to read
    # you will need the bucket name and the csv file name

    bucket = conn.get_bucket(bucket_name, validate=False)
    key = Key(bucket)
    key.key = remote_file_name
    data = key.get_contents_as_string()
    key.close()

    # you store it into a string, therefore you will need to split it
    # usually the split characters are '\r\n' if not just read the file normally 
    # and find out what they are 

    reader = csv.reader(data.split('\r\n'))
    data = []
    header = next(reader)
    for row in reader:
        data.append(row)

    return data

j'espère que cela a résolu votre problème, bonne chance! :)

5
BigDataSaurius

J'ai finalement réalisé que vous devez également définir les autorisations sur chaque objet individuel dans le compartiment afin de l'extraire en utilisant le code suivant:

from boto.s3.key import Key
k = Key(bucket)
k.key = 'data_1.csv'
k.set_canned_acl('public-read')

Et j'ai également dû modifier l'adresse du compartiment dans la commande pd.read_csv comme suit:

data = pd.read_csv('https://s3-ap-southeast-2.amazonaws.com/example_bucket/data_1.csv')
3
Paul_M

Basé sur cette réponse qui a suggéré d'utiliser smart_open pour la lecture de S3, voici comment je l'ai utilisé avec Pandas:

import os
import pandas as pd
from smart_open import smart_open

aws_key = os.environ['AWS_ACCESS_KEY']
aws_secret = os.environ['AWS_SECRET_ACCESS_KEY']

bucket_name = 'my_bucket'
object_key = 'my_file.csv'

path = 's3://{}:{}@{}/{}'.format(aws_key, aws_secret, bucket_name, object_key)

df = pd.read_csv(smart_open(path))
1
kepler