2016-07-01 52 views
18

Ho un DataFrame panda che voglio caricare su un nuovo file CVS. Il problema è che non voglio salvare il file localmente prima di trasferirlo su s3. Esiste un metodo come to_csv per scrivere direttamente il dataframe su s3? Sto usando boto3.
Ecco quello che ho finora:Salva Dataframe in csv direttamente su s3 Python

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 

risposta

7

Se si passa None come primo argomento a to_csv() i dati saranno restituiti sotto forma di stringa. Da lì è un semplice passaggio per caricarlo su S3 in un colpo solo.

Dovrebbe anche essere possibile passare un oggetto StringIO a to_csv(), ma l'utilizzo di una stringa sarà più semplice.

+0

sarà più facile in che modo? Qual è il modo corretto per farlo? –

+0

@EranMoshe: in entrambi i casi funzionerà correttamente, ma ovviamente è più semplice passare 'None' a' to_csv() 'e utilizzare la stringa restituita piuttosto che creare un oggetto' StringIO' e quindi leggere i dati nuovamente. – mhawke

+0

Come programmatore pigro è quello che ho fatto. E tu intendevi più facile per il programmatore che scrive meno codice:> –

21

È possibile utilizzare:

from io import StringIO 
import boto3 

csv_buffer = StringIO() 
df.to_csv(csv_buffer) 
s3_resource = boto3.resource('s3') 
s3_resource.Object(bucket, 'df.csv').put(Body=csv_buffer.getvalue()) 
+0

da io import StringIO, quindi non sembra consentire modifiche di meno di 6 caratteri. – Satyadev

+0

Se questo è un file di grandi dimensioni, cosa fa questo in memoria ...? – citynorman

+0

Se il file è più grande, la RAM che hai a disposizione l'azione avrà esito negativo e farà eccezione ad eccezione (non so quale). Questa dovrebbe essere accettata come risposta –

0
import boto3 

    s3_client = boto3.client('s3',aws_access_key_id="AccessKey",aws_secret_access_key="Secretkey") 

    head_response = s3_client.head_object(Bucket='YourBucket',Key='YourPath') 

    if head_response['HTTPStatusCode'] == 200: 
      Your operation if file exsits 
14

mi piace s3fs che consente di utilizzare s3 (quasi) come un file system locale.

Si può fare questo:

import s3fs 

bytes_to_write = df.to_csv(None).encode() 
fs = s3fs.S3FileSystem(key=key, secret=secret) 
with fs.open('s3://bucket/path/to/file.csv', 'wb') as f: 
    f.write(bytes_to_write) 

s3fs supporta solo rb e wb modalità di apertura del file, è per questo che ho fatto questa roba bytes_to_write.

+0

Grande! Come posso ottenere l'url del file usando lo stesso modulo s3fs? –

+0

@ M.Zaman, non sono sicuro di cosa stai chiedendo. – michcio1234

+0

Stavo cercando l'URL da cui posso scaricare il file scritto, comunque lo prendo tramite S3FileSystem. Grazie –

0

Ho letto un csv con due colonne da bucket s3 e il contenuto del file csv ho inserito in dataframe panda.

Esempio:

config.json

{ 
    "credential": { 
    "access_key":"xxxxxx", 
    "secret_key":"xxxxxx" 
} 
, 
"s3":{ 
     "bucket":"mybucket", 
     "key":"csv/user.csv" 
    } 
} 

cls_config.json

#!/usr/bin/env python 
# -*- coding: utf-8 -*- 

import os 
import json 

class cls_config(object): 

    def __init__(self,filename): 

     self.filename = filename 


    def getConfig(self): 

     fileName = os.path.join(os.path.dirname(__file__), self.filename) 
     with open(fileName) as f: 
     config = json.load(f) 
     return config 

cls_pandas.py

#!/usr/bin/env python 
# -*- coding: utf-8 -*- 

import pandas as pd 
import io 

class cls_pandas(object): 

    def __init__(self): 
     pass 

    def read(self,stream): 

     df = pd.read_csv(io.StringIO(stream), sep = ",") 
     return df 

cls_s3.py

#!/usr/bin/env python 
# -*- coding: utf-8 -*- 

import boto3 
import json 

class cls_s3(object): 

    def __init__(self,access_key,secret_key): 

     self.s3 = boto3.client('s3', aws_access_key_id=access_key, aws_secret_access_key=secret_key) 

    def getObject(self,bucket,key): 

     read_file = self.s3.get_object(Bucket=bucket, Key=key) 
     body = read_file['Body'].read().decode('utf-8') 
     return body 

test.py

#!/usr/bin/env python 
# -*- coding: utf-8 -*- 

from cls_config import * 
from cls_s3 import * 
from cls_pandas import * 

class test(object): 

    def __init__(self): 
     self.conf = cls_config('config.json') 

    def process(self): 

     conf = self.conf.getConfig() 

     bucket = conf['s3']['bucket'] 
     key = conf['s3']['key'] 

     access_key = conf['credential']['access_key'] 
     secret_key = conf['credential']['secret_key'] 

     s3 = cls_s3(access_key,secret_key) 
     ob = s3.getObject(bucket,key) 

     pa = cls_pandas() 
     df = pa.read(ob) 

     print df 

if __name__ == '__main__': 
    test = test() 
    test.process() 
+1

per favore non solo postare la soluzione, aggiungi anche una spiegazione. – sjaustirni

Problemi correlati