我通过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上拥有多个零件文件即可。但是当我下载本地副本时,我想合并。
答案 0 :(得分:2)
这可以使用AWS python SDK的boto3
相对简单的功能来完成。
解决方案涉及在给定密钥中列出part-*
个对象,然后下载每个对象并附加到文件对象。首先,列出文件夹path/to/my_file.json
中my_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