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!
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))
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! :)
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')
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))