J'ai un DataFrame pandas que je souhaite télécharger dans un nouveau fichier CSV. Le problème est que je ne veux pas enregistrer le fichier localement avant de le transférer vers s3. Existe-t-il une méthode comme to_csv pour écrire directement le dataframe dans s3? J'utilise boto3.
Voici ce que j'ai jusqu'à présent:
import boto3
s3 = boto3.client('s3', aws_access_key_id='key', aws_secret_access_key='secret_key')
read_file = s3.get_object(Bucket, Key)
df = pd.read_csv(read_file['Body'])
# Make alterations to DataFrame
# Then export DataFrame to CSV through direct transfer to s3
df.to_csv('s3://mybucket/dfs/somedf.csv')
. stackoverflow.com/a/56275519/908886 pour plus d'informations.Réponses:
Vous pouvez utiliser:
la source
TypeError: unicode argument expected, got 'str'
erreur lors de l'utilisationStringIO
. Je l'ai utiliséBytesIO
et cela a parfaitement fonctionné. Remarque: c'était en Python 2.7bucket
objet? comment as-tu créé ça?bucket
est l'endroit où vous stockez les objets sur S3. Le code suppose que vous avez déjà créé la destination (pensez: répertoire) où stocker cela. Voir la documentation S3Vous pouvez utiliser directement le chemin S3. J'utilise Pandas 0.24.1
Note de version:
la source
NoCredentialsError: Unable to locate credentials
. Aucune suggestion?NotImplementedError: Text mode not supported, use mode='wb' and manage bytes
. Aucune suggestion?J'aime s3fs qui vous permet d'utiliser s3 (presque) comme un système de fichiers local.
Tu peux le faire:
s3fs
prend en charge uniquementrb
et leswb
modes d'ouverture du fichier, c'est pourquoi j'ai fait cebytes_to_write
truc.la source
s3fs
ne semble pas prendre en charge le mode d'ajout.Voici une réponse plus à jour:
Le problème avec StringIO est qu'il va ronger votre mémoire. Avec cette méthode, vous diffusez le fichier en s3, plutôt que de le convertir en chaîne, puis vous l'écrivez en s3. Tenir le dataframe pandas et sa copie de chaîne en mémoire semble très inefficace.
Si vous travaillez dans un instant ec2, vous pouvez lui attribuer un rôle IAM pour lui permettre de l'écrire dans s3, vous n'avez donc pas besoin de transmettre directement les informations d'identification. Cependant, vous pouvez également vous connecter à un compartiment en transmettant des informations d'identification à la
S3FileSystem()
fonction. Voir la documentation: https://s3fs.readthedocs.io/en/latest/la source
to_csv()
. semble être une mise en œuvre plus propre.botocore.exceptions.ClientError: An error occurred (AccessDenied) when calling the PutObject operation: Access Denied
... J'ai même rendu le bucket PUBLIC READ et j'ai ajouté les actions suivantes, sous mon compte utilisateur IAM spécifique, dans la politique du bucket:"Action": [ "s3:PutObject", "s3:PutObjectAcl", "s3:GetObject", "s3:GetObjectAcl", "s3:DeleteObject" ]
def send_to_bucket(df, fn_out, bucketname): csv_buffer = StringIO(); df.to_csv(csv_buffer); s3_resource = boto3.resource('s3'); s3_resource.Object(bucketname, fn_out).put(Body=csv_buffer.getvalue());
Si vous passez
None
comme premier argument auxto_csv()
données, elles seront renvoyées sous forme de chaîne. À partir de là, il est facile de télécharger cela sur S3 en une seule fois.Il devrait également être possible de passer un
StringIO
objet àto_csv()
, mais l'utilisation d'une chaîne sera plus facile.la source
None
àto_csv()
et utiliser la chaîne retournée que de créer unStringIO
objet, puis lire les données arrière.J'ai trouvé que cela pouvait être fait en utilisant
client
aussi et pas seulementresource
.la source
Vous pouvez également utiliser AWS Data Wrangler :
Notez qu'il se divisera en plusieurs parties car il le télécharge en parallèle.
la source
depuis que vous utilisez
boto3.client()
, essayez:la source
J'ai trouvé une solution très simple qui semble fonctionner:
J'espère que cela pourra aider !
la source
J'ai lu un csv avec deux colonnes du bucket s3, et le contenu du fichier csv que j'ai mis dans pandas dataframe.
Exemple:
config.json
cls_config.json
cls_pandas.py
cls_s3.py
test.py
la source