ডেটাফ্রেম সিএসভিতে সরাসরি এস 3 পাইথনে সংরক্ষণ করুন


125

আমার কাছে একটি পান্ডাস ডেটা ফ্রেম রয়েছে যা আমি একটি নতুন সিএসভি ফাইলে আপলোড করতে চাই। সমস্যাটি হ'ল আমি ফাইলটি এস 3 এ স্থানান্তর করার আগে স্থানীয়ভাবে সংরক্ষণ করতে চাই না। সরাসরি এস 3-তে ডেটাফ্রেম লেখার জন্য টো_সিএসভি-এর মতো কোনও পদ্ধতি আছে কি? আমি বোটো 3 ব্যবহার করছি।
আমার এখন পর্যন্ত যা আছে তা এখানে:

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

3
df.to_csv('s3://mybucket/dfs/somedf.csv')। আরও তথ্যের জন্য stackoverflow.com/a/56275519/908886
পিটার বার্গ

উত্তর:


158

তুমি ব্যবহার করতে পার:

from io import StringIO # python3; python2: BytesIO 
import boto3

bucket = 'my_bucket_name' # already created on S3
csv_buffer = StringIO()
df.to_csv(csv_buffer)
s3_resource = boto3.resource('s3')
s3_resource.Object(bucket, 'df.csv').put(Body=csv_buffer.getvalue())

9
এটি যদি একটি বড় ফাইল হয় তবে এটি মেমরির সাথে কী করবে ...?
সিটিএনরম্যান

2
যদি ফাইলটি বড় হয় তবে আপনার যে র‌্যামটি উপলব্ধ রয়েছে তা অ্যাকশন ব্যর্থ হবে এবং ব্যতিক্রম ব্যতীত (কোনটি জানেন না)। এটি উত্তর হিসাবে গ্রহণ করা উচিত
এরান মোশে

5
TypeError: unicode argument expected, got 'str'ব্যবহার করার সময় আমি ত্রুটি পেয়েছি StringIO। আমি ব্যবহার করেছি BytesIOএবং এটি পুরোপুরি সূক্ষ্মভাবে কাজ করেছে। দ্রষ্টব্য: এটি পাইথন ২.7 এ ছিল
অভিষেক উপাধ্যায়

1
bucketআপত্তি কি ? কিভাবে আপনি এটি তৈরি?
চার্লস চৌ চৌ

1
bucketআপনি যেখানে S3 এ অবজেক্টগুলি সঞ্চয় করেন। কোডটি ধরে নিয়েছে আপনি ইতিমধ্যে গন্তব্য (ভাবুন: ডিরেক্টরি) এটি কোথায় সংরক্ষণ করবেন তা তৈরি করেছেন। এস 3 ডক্স
স্টেফান

65

আপনি সরাসরি এস 3 পাথ ব্যবহার করতে পারেন। আমি পান্ডা ব্যবহার করছি 0.24.1

In [1]: import pandas as pd

In [2]: df = pd.DataFrame( [ [1, 1, 1], [2, 2, 2] ], columns=['a', 'b', 'c'])

In [3]: df
Out[3]:
   a  b  c
0  1  1  1
1  2  2  2

In [4]: df.to_csv('s3://experimental/playground/temp_csv/dummy.csv', index=False)

In [5]: pd.__version__
Out[5]: '0.24.1'

In [6]: new_df = pd.read_csv('s3://experimental/playground/temp_csv/dummy.csv')

In [7]: new_df
Out[7]:
   a  b  c
0  1  1  1
1  2  2  2

রিলিজ নোট:

এস 3 ফাইল হ্যান্ডলিং

পান্ডস এখন এস 3 সংযোগগুলি পরিচালনা করার জন্য s3fs ব্যবহার করে। এটি কোনও কোড ভাঙা উচিত নয়। তবে s3fs যেহেতু প্রয়োজনীয় নির্ভরতা নয়, আপনাকে পান্ডার পূর্ববর্তী সংস্করণগুলিতে বোটোর মতো আলাদাভাবে ইনস্টল করতে হবে। জিএইচ 11915


7
এটি অবশ্যই এখন সবচেয়ে সহজ উত্তর, এটি পর্দার পিছনে s3fs ব্যবহার করে যাতে আপনার এটি আপনার প্রয়োজনীয়তার সাথে যুক্ত করা দরকার t txt
জেডি ডি

1
আমি পছন্দ করি এটি সহজ, তবে মনে হচ্ছে এটি কার্যকরভাবে কাজ করছে না কারণ আমি নিম্নলিখিত ত্রুটিটি পেয়ে চলেছি NoCredentialsError: Unable to locate credentials। কোনও পরামর্শ?
ক্যাথিকিয়ান

1
আমি এই পান্ডাস <= 0.23.4 সাথে কাজ করে না তা নিশ্চিত করতে পারেন হতে তাই, নিশ্চিত করুন পান্ডাস আপগ্রেড করার 0.24
গাইডো

1
টাইপ-এআরআর to_csv কমান্ডটি ব্যবহার করার চেষ্টা করার সময় আমি এই ত্রুটিটি দেখি: লিখুন () যুক্তিটি 1 টি ইউনিকোড হতে হবে, স্ট্রিং নয়
রাজ

13
আমি পান্ডাস 0.24.2 ব্যবহার করছি এবং যা পাই তা হ'ল NotImplementedError: Text mode not supported, use mode='wb' and manage bytes। কোনও পরামর্শ?
বিনিয়ামিন এমনকি

57

আমি s3fs পছন্দ করি যা আপনাকে স্থানীয় ফাইল সিস্টেমের মতো এস 3 (প্রায়) ব্যবহার করতে দেয়।

তুমি এটি করতে পারো:

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কেবলমাত্র rbএবং wbফাইলটি খোলার মোডগুলিকে সমর্থন করে, এই কারণেই আমি এই bytes_to_writeজিনিসটি করেছি।


গ্রেট! একই s3fs মডিউলটি ব্যবহার করে আমি কীভাবে ফাইল url পেতে পারি?
এম জামান

আমি ইউআরএলটি খুঁজছিলাম যেখানে থেকে আমি লিখিত ফাইলটি ডাউনলোড করতে পারি, যাইহোক আমি এস 3 ফাইল সিস্টেমের মাধ্যমে এটি পাই get ধন্যবাদ
এম জামান

এটাই আমি ব্যবহার করি; ধন্যবাদ। আমি কৌতূহল যে কেন পিডি.রেড_সিএসভি (<s3path>) আশানুরূপ কাজ করে তবে লেখার জন্য আমাদের এই কাজটি প্রায় ব্যবহার করতে হবে .. আমি যেভাবে আমার বৃহত্তরটি এস uc বালতিতে সরাসরি লিখছি তা বাদে
রেনি

@ michcio1234 কীভাবে আমি অ্যাপেন্ড মোডে একই কাজ করতে পারি? আমার বিদ্যমান সিএসভিতে ডেটা যুক্ত করতে হবে এস 3
জে

@j ' s3fsঅ্যাডেন্ড মোড সমর্থন করে না বলে মনে হচ্ছে।
michcio1234

43

এটি একটি আপ টু ডেট উত্তর:

import s3fs

s3 = s3fs.S3FileSystem(anon=False)

# Use 'w' for py3, 'wb' for py2
with s3.open('<bucket-name>/<filename>.csv','w') as f:
    df.to_csv(f)

স্ট্রিংআইওর সমস্যা হ'ল এটি আপনার স্মৃতি থেকে দূরে সরে যাবে। এই পদ্ধতির সাহায্যে আপনি ফাইলটি স্ট্রিংয়ে রূপান্তরিত না করে s3 এ স্ট্রিমিং করছেন, তারপরে এটি এস-তে লিখবেন। পান্ডাস ডেটা ফ্রেম এবং স্মৃতিতে এর স্ট্রিং কপিটি ধরে রাখা খুব অযোগ্য বলে মনে হচ্ছে।

আপনি যদি কোনও ই সি 2 তাত্ক্ষণিক্যে কাজ করে থাকেন তবে এস -3 এ এটি লেখার সক্ষম করার জন্য আপনি এটি একটি আইএএম ভূমিকা দিতে পারেন, সুতরাং আপনাকে সরাসরি শংসাপত্রগুলি পাস করার প্রয়োজন হবে না। তবে, আপনি S3FileSystem()ফাংশনে শংসাপত্রগুলি প্রেরণ করে একটি বালতিতেও সংযোগ করতে পারেন । নথিপত্র দেখুন: https://s3fs.readthedocs.io/en/latest/


কোনও কারণে যখন আমি এটি করেছি তখন প্রতিটি লাইন CSV
kjmerf

হুম। কেন যে ঘটবে তা নিশ্চিত নয়। আপনি কি এখনও সমস্যা পান কিনা তা দেখার জন্য সম্ভবত অন্য প্যান্ডাস ডিএফ দিয়ে চেষ্টা করুন? যদি আপনার পান্ডসের সংস্করণ এটি সমর্থন করে তবে @ অমিত-কুশওয়াহার জবাবটি চেষ্টা করুন, যেখানে আপনি এস 3 ইউআরএল সরাসরি পাঠিয়েছেন to_csv()। একটি ক্লিনার বাস্তবায়ন মনে হচ্ছে।
erncyp

@ আর্জেন্টি আমি সেখানে ত্রুটি পেয়ে যাচ্ছি বলে মনে হচ্ছে: botocore.exceptions.ClientError: An error occurred (AccessDenied) when calling the PutObject operation: Access Denied ... আমি বালতিটি পাবলিক "Action": [ "s3:PutObject", "s3:PutObjectAcl", "s3:GetObject", "s3:GetObjectAcl", "s3:DeleteObject" ]
রিডও করে দিয়েছি

মনে হচ্ছে আপনি অনুমতি অনুপস্থিত? আপনি যে আইএএম ভূমিকাটি ব্যবহার করছেন তার সাথে S3 পড়ার লিখনের অনুমতিগুলি সংযুক্ত করার বিষয়ে নিশ্চিত হন
erncyp

@ আর্জেন্টিপ আমার আইএএম ব্যবহারকারীর সাথে অ্যাডমিনিস্ট্রেটরঅ্যাক্সেস নীতি রয়েছে, সুতরাং তত্ত্বের ভিত্তিতে আমার ঠিক সূক্ষ্মভাবে পড়তে / লিখতে সক্ষম হওয়া উচিত ... অদ্ভুতভাবে আমি অন্য স্ট্যাকওভারফ্লো ব্যবহারকারীর ব্যবহার করে আমার তৈরি নিম্নলিখিত ফাংশনটি ব্যবহার করার সময় ঠিক ঠিক লিখতে সক্ষম হয়েছি পরামর্শ (এফআইআই আধা-কলোনগুলি শেষের লাইনের পরে আমি মন্তব্য বিভাগে ফর্ম্যাট করতে জানি না):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());
এজোরোস

13

যদি আপনি Noneপ্রথম যুক্তি হিসাবে পাসto_csv() ডেটাতে স্ট্রিং হিসাবে ফিরে আসবে। সেখান থেকে একসাথে এস 3 এ আপলোড করা সহজ পদক্ষেপ।

এটিতে কোনও StringIOবস্তুটি পাস করাও সম্ভব উচিত to_csv()তবে স্ট্রিং ব্যবহার করা আরও সহজ হবে।


কোন উপায়ে সহজ হবে? এটি করার সঠিক উপায় কী?
ইরান মোশে

@ ইরানমোশে: যে কোনও উপায়ে সঠিকভাবে কাজ করবে, তবে প্রত্যাবর্তিত স্ট্রিংটি পাস Noneকরা to_csv()এবং ব্যবহার করা সহজভাবে কোনও StringIOঅবজেক্ট তৈরি করা এবং তারপরে ডেটা ফেরত পাঠানো সহজ।
mhakke

অলস প্রোগ্রামার হিসাবে আমি এটিই করেছি। এবং আপনি সেই প্রোগ্রামারটির পক্ষে আরও সহজ বোঝাচ্ছেন যিনি কম কোড লেখেন:>
এরান মোশে

2

আপনি এডাব্লুএস ডেটা র্যাংলারও ব্যবহার করতে পারেন :

import awswrangler

session = awswrangler.Session()
session.pandas.to_csv(
    dataframe=df,
    path="s3://...",
)

মনে রাখবেন যে এটি সমান্তরালে এটি আপলোড হওয়ায় এটি বেশ কয়েকটি অংশে বিভক্ত হবে।


2

আমি দেখেছি এটি ব্যবহার clientকরেও করা যেতে পারে এবং কেবল নয় resource

from io import StringIO
import boto3
s3 = boto3.client("s3",\
                  region_name=region_name,\
                  aws_access_key_id=aws_access_key_id,\
                  aws_secret_access_key=aws_secret_access_key)
csv_buf = StringIO()
df.to_csv(csv_buf, header=True, index=False)
csv_buf.seek(0)
s3.put_object(Bucket=bucket, Body=csv_buf.getvalue(), Key='path/test.csv')

0

আপনি যেহেতু ব্যবহার করছেন তাই boto3.client()চেষ্টা করুন:

import boto3
from io import StringIO #python3 
s3 = boto3.client('s3', aws_access_key_id='key', aws_secret_access_key='secret_key')
def copy_to_s3(client, df, bucket, filepath):
    csv_buf = StringIO()
    df.to_csv(csv_buf, header=True, index=False)
    csv_buf.seek(0)
    client.put_object(Bucket=bucket, Body=csv_buf.getvalue(), Key=filepath)
    print(f'Copy {df.shape[0]} rows to S3 Bucket {bucket} at {filepath}, Done!')

copy_to_s3(client=s3, df=df_to_upload, bucket='abc', filepath='def/test.csv')

-1

আমি একটি খুব সাধারণ সমাধান পেয়েছি যা মনে হচ্ছে এটি কাজ করছে:

s3 = boto3.client("s3")

s3.put_object(
    Body=open("filename.csv").read(),
    Bucket="your-bucket",
    Key="your-key"
)

আশা করি এইটি কাজ করবে !


-5

আমি বালতি এস 3 থেকে দুটি কলাম সহ একটি সিএসভি এবং প্যানডাস ডেটাফ্রেমে আমি সিএসভি ফাইলটি রেখেছি।

উদাহরণ:

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()

4
দয়া করে কেবল সমাধান পোস্ট করবেন না, এটির একটি ব্যাখ্যাও যুক্ত করুন।
sjaustirni

এরকম জটিল (পাইথনের নবজাতকের জন্য) সমাধান তৈরি করার কোনও সুবিধা আছে কি?
জাভিয়ের লোপেজ টমস

1
এটি এস 3 থেকে একটি ফাইল পড়বে, প্রশ্নটি ছিল ডিফ থেকে এস 3 কীভাবে লিখবেন।
দামিয়ান স্যাটারথওয়েট-ফিলিপস
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.