簡體   English   中英

從私有 S3 存儲桶讀取文件到 pandas dataframe

[英]Reading a file from a private S3 bucket to a pandas dataframe

我正在嘗試將 CSV 文件從私有 S3 存儲桶讀取到 pandas dataframe:

df = pandas.read_csv('s3://mybucket/file.csv')

我可以從公共存儲桶讀取文件,但從私有存儲桶讀取文件會導致 HTTP 403:禁止錯誤。

我已經使用 aws configure 配置了 AWS 憑證。

我可以使用使用 aws 憑據的 boto3 從私有存儲桶下載文件。 看來我需要配置 pandas 才能使用 AWS 憑證,但不知道如何配置。

Pandas 在read_csv使用boto (不是boto3 )。 您也許可以安裝 boto 並使其正常工作。

boto 和 python 3.4.4 / python3.5.1 存在一些問題 如果您在這些平台上,並且在修復這些平台之前,您可以使用 boto 3 作為

import boto3
import pandas as pd

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

那個obj有一個.read方法(它返回一個字節流),這對熊貓來說已經足夠了。

為 Pandas 0.20.1 更新

Pandas 現在使用 s3fs 來處理 s3 連接。 關聯

pandas 現在使用 s3fs 來處理 S3 連接。 這不應該破壞任何代碼。 但是,由於 s3fs 不是必需的依賴項,因此您需要單獨安裝它,就像以前版本的 Pandas 中的 boto 一樣。

import os

import pandas as pd
from s3fs.core import S3FileSystem

# aws keys stored in ini file in same path
# refer to boto3 docs for config settings
os.environ['AWS_CONFIG_FILE'] = 'aws_config.ini'

s3 = S3FileSystem(anon=False)
key = 'path\to\your-csv.csv'
bucket = 'your-bucket-name'

df = pd.read_csv(s3.open('{}/{}'.format(bucket, key), mode='rb'))
# or with f-strings
df = pd.read_csv(s3.open(f'{bucket}/{key}', mode='rb'))

大熊貓 0.22 及更高版本的更新:

如果您已經安裝了 s3fs ( pip install s3fs ),那么您可以直接從 s3 路徑讀取文件,無需任何導入:

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

穩定的文檔

基於這個答案,我發現smart_open使用起來要簡單得多:

import pandas as pd
from smart_open import smart_open

initial_df = pd.read_csv(smart_open('s3://bucket/file.csv'))
import pandas as pd
import boto3
from io import StringIO

# Read CSV
s3 = boto3.client('s3',endpoint_url,aws_access_key_id=,aws_secret_access_key)
read_file = s3.get_object(Bucket, Key)
df = pd.read_csv(read_file['Body'],sep=',')

# Write CSV
csv_buffer = StringIO()
df.to_csv(csv_buffer)
s3.put_object(Bucket, Key,Body=csv_buffer.getvalue())

在不使用 s3fs 的情況下更新 pandas 0.20.3:

import boto3
import pandas as pd
import sys

if sys.version_info[0] < 3: 
    from StringIO import StringIO # Python 2.x
else:
    from io import StringIO # Python 3.x

s3 = boto3.client('s3')
obj = s3.get_object(Bucket='bucket', Key='key')
body = obj['Body']
csv_string = body.read().decode('utf-8')

df = pd.read_csv(StringIO(csv_string))

除了其他很棒的答案之外,如果需要自定義端點,還可以通過猴子修補 s3fs init 方法來使用pd.read_csv('s3://...')語法。

import s3fs
s3fsinit = s3fs.S3FileSystem.__init__
def s3fsinit_patched(self, *k, *kw):
    s3fsinit(self, *k, client_kwargs={'endpoint_url': 'https://yourcustomendpoint'}, **kw)
s3fs.S3FileSystem.__init__ = s3fsinit_patched

或者,更優雅的方式:

import s3fs
class S3FileSystemPatched(s3fs.S3FileSystem):
    def __init__(self, *k, **kw):
        super(S3FileSystemPatched, self).__init__( *k,
                                                  key = os.environ['aws_access_key_id'],
                                                  secret = os.environ['aws_secret_access_key'],
                                                  client_kwargs={'endpoint_url': 'https://yourcustomendpoint'},
                                                  **kw)
        print('S3FileSystem is patched')
s3fs.S3FileSystem = S3FileSystemPatched

另請參閱: s3fs 自定義端點 url

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

您還可以手動使用憑據。

請注意,如果你的水桶是私人和一個AWS般的供應商,你會遇到錯誤, s3fs不會在加載配置文件配置文件~/.aws/configawscli

一種解決方案是定義當前環境變量:

export AWS_S3_ENDPOINT="myEndpoint"
export AWS_DEFAULT_REGION="MyRegion"

以前的答案是一個很好的基本開始,但我想實現下面所述的高級目標。 總的來說,我覺得awswrangler是要走的路。

  1. 閱讀 .gzip
  2. 只讀取前 5 行而不下載完整文件
  3. 顯式傳遞憑據(確保不要將它們提交到代碼中!!)
  4. 使用完整的 s3 路徑

以下是一些有效的方法


import boto3
import pandas as pd
import awswrangler as wr

boto3_creds = dict(region_name="us-east-1", aws_access_key_id='', aws_secret_access_key='')
boto3.setup_default_session(**boto3_creds)

s3 = boto3.client('s3')

# read first 5 lines from file path
obj = s3.get_object(Bucket='bucket', Key='path.csv.gz')
df = pd.read_csv(obj['Body'], nrows=5, compression='gzip')

# read first 5 lines from directory
dft_xp = pd.concat(list(wr.s3.read_csv(wr.s3.list_objects('s3://bucket/path/')[0], chunksize=5, nrows=5, compression='gzip')))

# read all files into pandas
df_xp = wr.s3.read_csv(wr.s3.list_objects('s3://bucket/path/'), compression='gzip')

沒有使用 s3fs 不確定它是否使用 boto3。

對於帶有 dask 的分布式計算,這可行,但它使用 s3fs afaik 並且顯然 gzip 不能並行化。


import dask.dataframe as dd

dd.read_csv('s3://bucket/path/*', storage_options={'key':'', 'secret':''}, compression='gzip').head(5)

dd.read_csv('s3://bucket/path/*', storage_options={'key':'', 'secret':''}, compression='gzip') 
# Warning gzip compression does not support breaking apart files Please ensure that each individual file can fit in memory
 

要在這里添加到其他的解決方案提供更多最新更新: pandasfsspecs3fs已全部更新,這樣你可以使用熊貓沒有其他進口自定義端點和直接讀取。 你必須確保你不僅fsspecs3fs安裝,因為它們是大熊貓可選的依賴。

然后你可以使用

import pandas as pd

pd.read_csv(
    's3://mybucket/file.csv',
    storage_options = {
        client_kwargs = {
            'endpoint_url': <MY_S3_ENDPOINT_URL>
        }
    }

它笨重,但由於某種原因,作為boto3維護者, boto3一直拒絕更新庫以允許在客戶端構建之外(即在配置文件或環境變量中)進行自定義端點配置。 但是,如果你並不需要讀/通過大熊貓書面形式, awswrangler也許是因為其他人所說的更好。

您可以將AWS SDK 用於 Pandas ,這是一個擴展 Pandas 的庫,可以與 AWS 數據存儲(例如 S3)順利協作。

import awswrangler as wr
df = wr.s3.read_csv("s3://bucket/file.csv")

它可以通過pip install awswrangler

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM