如何使用flatMap()在PySpark中并行列出S3对象?

时间:2018-10-31 22:40:34

标签: apache-spark amazon-s3 pyspark apache-spark-sql boto3

我有一个数据框,其中每一行都包含一个指向S3中某个位置的前缀。我想使用flatMap()遍历每一行,在每个前缀中列出S3对象,并返回一个新的数据框,该数据框包含每个文件在S3中列出的一行。

我有以下代码:

import boto3
s3 = boto3.resource('s3')

def flatmap_list_s3_files(row):
    bucket = s3.Bucket(row.bucket)
    s3_files = []
    for obj in bucket.objects.filter(Prefix=row.prefix):
        s3_files.append(obj.key)

    rows = []
    for f in s3_files:
        row_dict = row.asDict()
        row_dict['s3_obj'] = f
        rows.append(Row(**row_dict))
    return rows

df = <code that loads the dataframe>
df.rdd.flatMap(lambda x: flatmap_list_s3_files(x))).toDF()

唯一的问题是我猜s3对象不是可腌制的吗?所以我遇到了这个错误,我不确定下一步该怎么做:

PicklingError: Cannot pickle files that are not opened for reading

我是一个火花新手,所以我希望有一些其他API或某种方式可以并行化S3中的文件列表,并将其与原始数据帧结合在一起。需要明确的是,我并不是要读取S3文件中的任何数据,而是要建立一个表,该表实质上是S3中所有文件的元数据目录。任何提示将不胜感激。

1 个答案:

答案 0 :(得分:0)

您无法在Spark集群周围发送s3客户端;您需要共享创建信息并在远端实例化它所需的所有信息。我对.py不了解,但是在Java API中,您只是将路径作为字符串传递,然后将其转换为Path对象,调用Path.getFileSystem()并在那里进行操作。 Spark工作者将缓存文件系统实例以快速重用