2016-07-01 8 views
18

Ich habe eine Pandas DataFrame, die ich in eine neue CVS-Datei hochladen möchte. Das Problem ist, dass ich die Datei nicht lokal speichern möchte, bevor ich sie an s3 übertrage. Gibt es eine Methode wie to_csv, um den Datenrahmen direkt an s3 zu schreiben? Ich benutze Boto3.
Hier ist, was ich bisher:Speichern von Datenrahmen in CSV direkt in 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 

Antwort

7

Wenn Sie None als erstes Argument zu to_csv() die Daten als String zurückgegeben werden passieren. Von dort aus ist es ein einfacher Schritt, das in S3 auf einmal hochzuladen.

Es sollte auch möglich sein, ein StringIO Objekt an to_csv() zu übergeben, aber die Verwendung einer Zeichenfolge wird einfacher.

+0

Wird in welcher Art und Weise einfacher sein? Was ist der richtige Weg? –

+0

@EranMoshe: jeder Weg wird richtig funktionieren, aber offensichtlich ist es einfacher, 'None' zu' to_csv() 'zu übergeben und den zurückgegebenen String zu verwenden, als ein' StringIO' Objekt zu erstellen und die Daten dann wieder auszulesen. – mhawke

+0

Als fauler Programmierer habe ich das gemacht. Und du bedeutest einfacher für den Programmierer, der weniger Code schreibt:> –

21

können Sie verwenden:

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

von io importieren StringIO, so scheint nicht Bearbeitungen weniger als 6 Zeichen zu erlauben. – Satyadev

+0

Wenn das eine große Datei ist, was macht das mit Speicher ...? – citynorman

+0

Wenn die Datei größer als der RAM ist, den Sie zur Verfügung haben, schlägt die Aktion fehl und wird eine Ausnahme (nicht wissen, welche). Dies sollte als Antwort akzeptiert werden –

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

ich s3fs mag, die Sie s3 (fast) wie ein lokales Dateisystem verwenden können.

Sie können dies tun:

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 unterstützen nur rb und wb Weisen Öffnen der Datei, das ist, warum ich diese bytes_to_write Sachen tat.

+0

Großartig! Wie kann ich die Datei-URL mit demselben s3fs-Modul erhalten? –

+0

@ M.Zaman, ich bin mir nicht sicher, worüber du fragst. – michcio1234

+0

Ich suchte nach der URL von wo ich die geschriebene Datei herunterladen kann, jedenfalls bekomme ich das über S3FileSystem. Vielen Dank –

0

Ich las eine CSV mit zwei Spalten aus dem Bucket s3, und den Inhalt der Datei CSV Ich pandas Dataframe einfügen.

Beispiel:

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

Bitte posten Sie nicht nur die Lösung, fügen Sie eine Erklärung dafür hinzu. – sjaustirni