ディスクに書き込まずにAWSS3のテキストファイルをパンダにインポートする方法


96

タブ区切りのテーブルであるテキストファイルをS3に保存しています。パンダにロードしたいのですが、herokuサーバーで実行しているため、最初に保存できません。これが私がこれまでに持っているものです。

import io
import boto3
import os
import pandas as pd

os.environ["AWS_ACCESS_KEY_ID"] = "xxxxxxxx"
os.environ["AWS_SECRET_ACCESS_KEY"] = "xxxxxxxx"

s3_client = boto3.client('s3')
response = s3_client.get_object(Bucket="my_bucket",Key="filename.txt")
file = response["Body"]


pd.read_csv(file, header=14, delimiter="\t", low_memory=False)

エラーは

OSError: Expected file path name or file-like object, got <class 'bytes'> type

応答本文をパンダが受け入れる形式に変換するにはどうすればよいですか?

pd.read_csv(io.StringIO(file), header=14, delimiter="\t", low_memory=False)

returns

TypeError: initial_value must be str or None, not StreamingBody

pd.read_csv(io.BytesIO(file), header=14, delimiter="\t", low_memory=False)

returns

TypeError: 'StreamingBody' does not support the buffer interface

更新-以下を使用して

file = response["Body"].read()

そして

pd.read_csv(io.BytesIO(file), header=14, delimiter="\t", low_memory=False)

:それをこの方法を試してみてくださいio.BytesIO(file)またはio.StringIO(file)代わりのfileread_csv()のコール
MaxU

この回答のio.StringIOように使用できます。
IanS 2016年

これらの提案はどちらも機能しませんでした。あなたは私の投稿編集でエラーを見ることができます。
alpalalpal 2016年

1
UPDATEの部分は私のために働いた。ありがとう。
Wim Berchmans 2016年

回答:


115

pandasを使用するbotoためread_csv、次のことができるはずです。

import boto
data = pd.read_csv('s3://bucket....csv')

boto3あなたが上python3.4+にいるのであなたが必要とするならば、あなたはすることができます

import boto3
import io
s3 = boto3.client('s3')
obj = s3.get_object(Bucket='bucket', Key='key')
df = pd.read_csv(io.BytesIO(obj['Body'].read()))

以来、バージョン0.20.1 pandasの用途s3fs、以下の回答を参照してください。


すべての人に公開せずにURLを使用する方法はありますか?ファイルは非公開にする必要があります。
alpalalpal 2016年

boto3:あなたにもプライベートなファイルにアクセスできるように、ドキュメントには、configure認証する方法を示しboto3.readthedocs.io/en/latest/guide/quickstart.html
ステファン・

1
NoCredentialsErrorをスローしています。s3認証情報を設定するにはどうすればよいですか?私はPythonとBotoを初めて使用します
Sunil Rao

15
:私はboto3で最後の例に次のことをしなければならなかったことが判明 df = pd.read_csv(io.BytesIO(obj['Body'].read()), encoding='utf8')
user394430

この回答は古くなっていますWesamsの回答をご覧ください。
ヘリット

84

これで、パンダはS3URLを処理できます。あなたは簡単に行うことができます:

import pandas as pd
import s3fs

df = pd.read_csv('s3://bucket-name/file.csv')

s3fs持ちでない場合はインストールする必要があります。 pip install s3fs

認証

S3バケットがプライベートで認証が必要な場合は、次の2つのオプションがあります。

1-構成ファイルにアクセス資格情報を追加し~/.aws/credentialsます

[default]
aws_access_key_id=AKIAIOSFODNN7EXAMPLE
aws_secret_access_key=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY

または

2-次の環境変数を適切な値で設定します。

  • aws_access_key_id
  • aws_secret_access_key
  • aws_session_token

綺麗な。python3で動作します。
カイラーブラウン

認証はどうですか..?
JamesWierzba19年

1
@JamesWierzba、上記の回答に認証の詳細を追加しました。
ウェサム

3
複数のawsプロファイルを処理する場合、どのプロファイルを使用するかをどのように選択できますか?s3fsにはprofile_nameオプションがありますが、それがパンダでどのように機能するかはわかりません。
IvoMerchiers19年

1
@IanS実際には、現在、最初にs3fsでファイルオブジェクトを開き(指定されたプロファイルを使用)、次にここで行うようにパンダで読み取りますgithub.com/pandas-dev/pandas/issues/16692
Ivo Merchiers

16

これは現在、最新のパンダでサポートされています。見る

http://pandas.pydata.org/pandas-docs/stable/io.html#reading-remote-files

例えば。、

df = pd.read_csv('s3://pandas-test/tips.csv')

4
「S3URLも処理されますが、S3Fライブラリをインストールする必要があります」ということを忘れないでください
JulioVillane19年

認証についてはどう
ですか

URLはパブリックとして公開されて、いない限りシンプル/基本的なHTTP認証は、動作する場合は認証付きのURLは確かに、難しいことではないかもしれ
Raveen Beemsingh

10

s3fsそれは次のように行うことができます。

import s3fs
import pandas as pd
fs = s3fs.S3FileSystem(anon=False)

# CSV
with fs.open('mybucket/path/to/object/foo.pkl') as f:
    df = pd.read_csv(f)

# Pickle
with fs.open('mybucket/path/to/object/foo.pkl') as f:
    df = pd.read_pickle(f)

2
s3fsを使えば、書くこともできると思いますdf = pd.read_csv('s3://mybucket/path/to/object/foo.pkl')
louis_guitton 2017

1
@louis_guittonこれはpd-read_csvで機能するようですが、read_pickleでは機能しないようです
Sip

2

ファイルが大きすぎる可能性があるため、ファイルをデータフレームに完全にロードすることは賢明ではありません。したがって、1行ずつ読み取り、データフレームに保存します。はい、read_csvでチャンクサイズを指定することもできますが、読み取った行数を維持する必要があります。

したがって、私はこのエンジニアリングを思いついた:

def create_file_object_for_streaming(self):
        print("creating file object for streaming")
        self.file_object = self.bucket.Object(key=self.package_s3_key)
        print("File object is: " + str(self.file_object))
        print("Object file created.")
        return self.file_object

for row in codecs.getreader(self.encoding)(self.response[u'Body']).readlines():
            row_string = StringIO(row)
            df = pd.read_csv(row_string, sep=",")

作業が完了したら、dfも削除します。 del df


1

テキストファイルの場合、パイプ区切りファイルで以下のコードを使用できます。例:-

import pandas as pd
import io
import boto3
s3_client = boto3.client('s3', use_ssl=False)
bucket = #
prefix = #
obj = s3_client.get_object(Bucket=bucket, Key=prefix+ filename)
df = pd.read_fwf((io.BytesIO(obj['Body'].read())) , encoding= 'unicode_escape', delimiter='|', error_bad_lines=False,header=None, dtype=str)

0

オプションは、を介してcsvをjsonに変換し、df.to_dict()それを文字列として保存することです。これは、CSVが要件ではないが、データフレームをS3バケットにすばやく入れて、再度取得したい場合にのみ関係することに注意してください。

from boto.s3.connection import S3Connection
import pandas as pd
import yaml

conn = S3Connection()
mybucket = conn.get_bucket('mybucketName')
myKey = mybucket.get_key("myKeyName")

myKey.set_contents_from_string(str(df.to_dict()))

これにより、dfがdict文字列に変換され、S3でjsonとして保存されます。後で同じjson形式で読むことができます。

df = pd.DataFrame(yaml.load(myKey.get_contents_as_string()))

他の解決策も良いですが、これは少し簡単です。Yamlは必ずしも必要ではないかもしれませんが、json文字列を解析するために何かが必要です。S3ファイルが必ずしもCSVである必要がない場合、これは簡単な修正になります。


0

Python 3.6以降の場合、Amazonには、awswranglerと呼ばれるPandasをサービスで使用するための非常に優れたライブラリがあります。

import awswrangler as wr
import boto3


# Boto3 session
session = boto3.session.Session(aws_access_key_id='XXXX', 
                                aws_secret_access_key='XXXX')

# Awswrangler pass forward all pd.read_csv() function args
df = wr.s3.read_csv(path='s3://bucket/path/',
                    boto3_session=session,
                    skiprows=2,
                    sep=';',
                    decimal=',',
                    na_values=['--'])

awswranglerをインストールするには: pip install awswrangler


-1
import s3fs
import pandas as pd
s3 = s3fs.S3FileSystem(profile='<profile_name>')
pd.read_csv(s3.open(<s3_path>))

1
コードに説明を追加してください。
andrey.shedko
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.