AWS S3의 텍스트 파일을 디스크에 쓰지 않고 Pandas로 가져 오는 방법


90

탭으로 구분 된 테이블 인 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

응답 본문을 Pandas가 허용하는 형식으로 어떻게 변환합니까?

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)대신 file에서 read_csv()호출
MaxU

이 답변io.StringIO 에서와 같이 사용할 수 있습니다 .
IANS

이러한 제안 중 어느 것도 효과가 없었습니다. 내 게시물 편집에서 오류를 볼 수 있습니다.
alpalalpal 2016-06-08

1
UPDATE 부분은 나를 위해 일했습니다. 감사.
Wim Berchmans

답변:


110

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-06-08

boto3: 워드 프로세서 구성 인증에 당신이 아니라 개인 파일에 액세스 할 수 있도록하는 방법을 보여 boto3.readthedocs.io/en/latest/guide/quickstart.html
스테판

1
NoCredentialsError가 발생합니다. s3 자격 증명을 어떻게 설정합니까? 저는 파이썬과 boto를 처음 접했습니다
Sunil Rao

15
: 나는 boto3와 마지막 예에서 다음을 수행 남겼 df = pd.read_csv(io.BytesIO(obj['Body'].read()), encoding='utf8')
user394430

이 답변은 오래되었습니다 . Wesams 답변을 참조하십시오 .
gerrit

79

이제 Pandas는 S3 URL을 처리 할 수 ​​있습니다 . 간단히 할 수 있습니다.

import pandas as pd
import s3fs

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

s3fs없는 경우 설치 해야합니다. pip install s3fs

입증

S3 버킷이 비공개이고 인증이 필요한 경우 다음 두 가지 옵션이 있습니다.

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에서 작동합니다.
Kyler Brown

인증은 어때 ..?
James Wierzba

1
@JamesWierzba, 위의 답변에 인증에 대한 자세한 내용을 추가했습니다.
Wesam

3
여러 AWS 프로필을 처리 할 때 사용할 프로필을 어떻게 선택할 수 있습니까? s3fs에는 profile_name 옵션이 있지만 팬더에서 어떻게 작동하는지 잘 모르겠습니다.
Ivo Merchiers 19

1
@IanS 현재는 s3fs (지정된 프로필 사용)로 파일 개체를 먼저 연 다음 여기에서하는 것처럼 pandas로 읽습니다. github.com/pandas-dev/pandas/issues/16692
Ivo Merchiers

15

이것은 이제 최신 팬더에서 지원됩니다. 보다

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

예 :

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

4
'S3 URL도 처리되지만 S3F 라이브러리를 설치해야 함'을 기억하십시오.
Julio Villane

인증은 어떻
습니까

인증이있는 URL은 URL이 공개로 노출되지 않는 한 어려울 수 있습니다. 단순 / 기본 http 인증이 작동하는지 확실하지 않습니다.
Raveen

9

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

1
@louis_guitton 이것은 pd-read_csv에서는 작동하지만 read_pickle에서는 작동하지 않는 것 같습니다
Sip

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 일 필요 가없는 경우 빠른 수정이 될 수 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.