Saya memiliki file teks yang disimpan di S3 yang merupakan tabel tab delimited. Saya ingin memuatnya ke dalam panda tetapi tidak dapat menyimpannya terlebih dahulu karena saya menjalankannya di server heroku. Inilah yang saya miliki sejauh ini.
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)
kesalahannya adalah
OSError: Expected file path name or file-like object, got <class 'bytes'> type
Bagaimana cara mengubah isi respons menjadi format yang akan diterima panda?
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
UPDATE - Menggunakan yang berikut ini berhasil
file = response["Body"].read()
dan
pd.read_csv(io.BytesIO(file), header=14, delimiter="\t", low_memory=False)
io.BytesIO(file)
atauio.StringIO(file)
bukanfile
dalamread_csv()
panggilanio.StringIO
seperti dalam jawaban ini .Jawaban:
pandas
digunakanboto
untukread_csv
, jadi Anda harus bisa:import boto data = pd.read_csv('s3://bucket....csv')
Jika Anda membutuhkan
boto3
karena Anda aktifpython3.4+
, Anda bisaimport boto3 import io s3 = boto3.client('s3') obj = s3.get_object(Bucket='bucket', Key='key') df = pd.read_csv(io.BytesIO(obj['Body'].read()))
Sejak versi 0.20.1
pandas
menggunakans3fs
, lihat jawaban di bawah.sumber
boto3
docs menunjukkan bagaimana otentikasi configure sehingga Anda dapat mengakses file pribadi juga: boto3.readthedocs.io/en/latest/guide/quickstart.htmldf = pd.read_csv(io.BytesIO(obj['Body'].read()), encoding='utf8')
Sekarang panda dapat menangani URL S3 . Anda cukup melakukan:
import pandas as pd import s3fs df = pd.read_csv('s3://bucket-name/file.csv')
Anda perlu menginstal
s3fs
jika Anda tidak memilikinya.pip install s3fs
Autentikasi
Jika bucket S3 Anda bersifat pribadi dan memerlukan autentikasi, Anda memiliki dua opsi:
1- Tambahkan kredensial akses ke file konfigurasi Anda
~/.aws/credentials
Atau
2- Atur variabel lingkungan berikut dengan nilai yang tepat:
aws_access_key_id
aws_secret_access_key
aws_session_token
sumber
Ini sekarang didukung di panda terbaru. Lihat
http://pandas.pydata.org/pandas-docs/stable/io.html#reading-remote-files
misalnya.,
df = pd.read_csv('s3://pandas-test/tips.csv')
sumber
Dengan s3fs dapat dilakukan sebagai berikut:
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)
sumber
df = pd.read_csv('s3://mybucket/path/to/object/foo.pkl')
Karena file bisa terlalu besar, tidak bijaksana untuk memuatnya ke dalam dataframe sama sekali. Karenanya, baca baris demi baris dan simpan di dataframe. Ya, kami juga dapat memberikan ukuran potongan di read_csv tetapi kemudian kami harus mempertahankan jumlah baris yang dibaca.
Oleh karena itu, saya menemukan teknik ini:
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=",")
Saya juga menghapus df setelah pekerjaan selesai.
del df
sumber
Untuk file teks, Anda dapat menggunakan kode di bawah ini dengan file yang dipisahkan tanda pipa misalnya: -
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)
sumber
Pilihannya adalah mengonversi csv ke json melalui
df.to_dict()
dan kemudian menyimpannya sebagai string. Perhatikan bahwa ini hanya relevan jika CSV bukan persyaratan, tetapi Anda hanya ingin meletakkan kerangka data dengan cepat di bucket S3 dan mengambilnya kembali.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()))
Ini akan mengubah df menjadi string dict, dan kemudian menyimpannya sebagai json di S3. Anda nanti dapat membacanya dalam format json yang sama:
Solusi lain juga bagus, tetapi ini sedikit lebih sederhana. Yaml mungkin tidak selalu diperlukan, tetapi Anda memerlukan sesuatu untuk mengurai string json. Jika file S3 tidak harus berupa CSV, ini bisa menjadi perbaikan cepat.
sumber