AWS下载所有Spark"部分 - *"文件并将它们合并到一个本地文件中

时间:2016-10-07 15:44:06

标签: json bash amazon-web-services apache-spark amazon-s3

我通过AWS上的数据库运行Spark作业,并通过调用

big_old_rdd.saveAsTextFile("path/to/my_file.json")

已将我的工作结果保存到AWS上的S3存储桶中。 spark命令的结果是包含结果部分的目录path/to/my_file.json

_SUCCESS
part-00000
part-00001
part-00002

等等。我可以使用AWS CLI使用相对简单的命令将这些部分文件复制到本地计算机:

aws s3 cp s3://my_bucket/path/to/my_file.json local_dir --recursive

现在我已经在本地获得了所有part-*个文件。然后我可以用

获得一个文件
cat $(ls part-*) > result.json

问题在于这个两阶段过程很麻烦,并且文件部分遍布整个地方。我想找到一个可以下载和合并文件的命令(理想情况是按顺序)。在直接处理HDFS时,这类似于hadoop fs -cat "path/to/my_file.json/*" > result.json

我已经浏览了AWS CLI文档,但还没有找到自动合并文件部分的选项,也没有找到文件。我对AWS API中的一些奇特工具或一些将结合上述命令的bash魔法感兴趣。

注意:通过spark将结果保存到单个文件中不是一个可行的选项,因为这需要在作业期间将数据合并到单个分区。如果不可取,​​在AWS上拥有多个零件文件即可。但是当我下载本地副本时,我想合并。

2 个答案:

答案 0 :(得分:2)

这可以使用AWS python SDK的boto3相对简单的功能来完成。

解决方案涉及在给定密钥中列出part-*个对象,然后下载每个对象并附加到文件对象。首先,列出文件夹path/to/my_file.jsonmy_bucket的零件文件:

import boto3
bucket = boto3.resource('s3').Bucket('my_bucket')
keys = [obj.key for obj in bucket.objects.filter(Prefix='path/to/my_file.json/part-')]

然后,将Bucket.download_fileobj()与以附加模式打开的文件一起使用来编写每个部分。我现在使用的功能,以及其他一些花里胡哨的功能是:

from os.path import basename

import boto3

def download_parts(base_object, bucket_name, output_name=None, limit_parts=0):
    """Download all file parts into a single local file"""

    base_object = base_object.rstrip('/')
    bucket = boto3.resource('s3').Bucket(bucket_name)
    prefix = '{}/part-'.format(base_object)
    output_name = output_name or basename(base_object)

    with open(output_name, 'ab') as outfile:
        for i, obj in enumerate(bucket.objects.filter(Prefix=prefix)):
            bucket.download_fileobj(obj.key, outfile)
            if limit_parts and i >= limit_parts:
                print('Terminating download after {} parts.'.format(i))
                break
        else:
            print('Download completed after {} parts.'.format(i))

答案 1 :(得分:1)

下载部分可能是额外的代码行。

cat按顺序而言,您可以根据创建的时间或按字母顺序执行此操作。

按创建时间顺序组合: cat $(ls -t) > outputfile

组合&按字母顺序排序: cat $(ls part-* | sort) > outputfile

组合&按字母顺序排序: cat $(ls part-* | sort -r) > outputfile