使用Boto3从S3存储桶读取多个csv文件

Nei*_*eil 2 python csv amazon-s3 boto3

我需要使用python中的boto3从S3存储桶中读取多个csv文件,最后将这些文件合并到熊猫的单个数据框中。

我能够从python中的以下脚本读取单个文件

 s3 = boto3.resource('s3')
 bucket = s3.Bucket('test-bucket')
 for obj in bucket.objects.all():
    key = obj.key
    body = obj.get()['Body'].read()
Run Code Online (Sandbox Code Playgroud)

以下是我的路

 files/splittedfiles/Code-345678
Run Code Online (Sandbox Code Playgroud)

Code-345678我有多个csv文件,我必须阅读并将其组合到大熊猫中的单个数据帧

另外,如何将选定Codes的列表作为列表传递,以便它仅读取那些文件夹。例如

files/splittedfiles/Code-345678
files/splittedfiles/Code-345679
files/splittedfiles/Code-345680
files/splittedfiles/Code-345681
files/splittedfiles/Code-345682
Run Code Online (Sandbox Code Playgroud)

从上面我只需要阅读以下代码下的文件。

345678,345679,345682
Run Code Online (Sandbox Code Playgroud)

如何在python中完成?

小智 13

修改答案1以克服错误DataFrame constructor not properly called!

代码:

import boto3
import pandas as pd
import io

s3 = boto3.resource('s3')
bucket = s3.Bucket('bucket_name')
prefix_objs = bucket.objects.filter(Prefix="folder_path/prefix")

prefix_df = []

for obj in prefix_objs:
    key = obj.key
    body = obj.get()['Body'].read()
    temp = pd.read_csv(io.BytesIO(body), encoding='utf8')        
    prefix_df.append(temp)
Run Code Online (Sandbox Code Playgroud)


vie*_*ind 6

boto3API不支持一次读取多个对象。您可以做的是检索具有指定前缀的所有对象,并使用循环加载每个返回的对象。为此,您可以使用filter()方法并将Prefix参数设置为要加载的对象的前缀。下面,我对您的代码进行了简单的更改,使您可以获取所有带有前缀“ files / splittedfiles / Code-345678”的对象,这些对象可以通过遍历可将每个文件加载到DataFrame的对象来读取:

s3 = boto3.resource('s3')
bucket = s3.Bucket('test-bucket')
prefix_objs = bucket.objects.filter(Prefix="files/splittedfiles/Code-345678")
for obj in prefix_objs:
    key = obj.key
    body = obj.get()['Body'].read()
Run Code Online (Sandbox Code Playgroud)

如果您有多个前缀,您将要进行评估,可以采用上述方法并将其转换为以前缀为参数的函数,然后将结果组合在一起。该函数可能是这样的:

import pandas as pd

def read_prefix_to_df(prefix):
    s3 = boto3.resource('s3')
    bucket = s3.Bucket('test-bucket')
    prefix_objs = bucket.objects.filter(Prefix=prefix)
    prefix_df = []
    for obj in prefix_objs:
        key = obj.key
        body = obj.get()['Body'].read()
        df = pd.DataFrame(body)
        prefix_df.append(df)
    return pd.concat(prefix_df)
Run Code Online (Sandbox Code Playgroud)

然后,您可以将该函数迭代地应用于每个前缀,并在最后合并结果。

  • `*** ValueError: DataFrame 构造函数未正确调用!` 答案可能已被弃用。`body` 是一个字节对象,我必须将其转换为 utf-8 指定的字符串编码,然后转换为 StringIO 对象,如下所示:/sf/ask/3316563351/ data-into-a-python-pandas-dataframe,但这只是将整个字符串设置为具有空值的列名。 (3认同)

小智 1

你可以这样做,使用“过滤器”而不是“全部”:

for obj in bucket.objects.filter(Prefix='files/splittedfiles/'):
    key = obj.key
    body = obj.get()['Body'].read()
Run Code Online (Sandbox Code Playgroud)