我习惯用Python编程。我公司现在安装了Jupyter的Hadoop集群。到现在为止,我从未使用过Spark / Pyspark。
我可以像以前一样轻松地从HDFS加载文件:
text_file = sc.textFile("/user/myname/student_grades.txt")
我能写出这样的输出:
text_file.saveAsTextFile("/user/myname/student_grades2.txt")
我想要实现的是使用简单的“for循环”逐个读取文本文件并将其内容写入一个HDFS文件。所以我尝试了这个:
list = ['text1.txt', 'text2.txt', 'text3.txt', 'text4.txt']
for i in list:
text_file = sc.textFile("/user/myname/" + i)
text_file.saveAsTextFile("/user/myname/all.txt")
所以这适用于列表的第一个元素,但后来给了我这个错误信息:
Py4JJavaError: An error occurred while calling o714.saveAsTextFile.
: org.apache.hadoop.mapred.FileAlreadyExistsException: Output directory
XXXXXXXX/user/myname/all.txt already exists
为了避免混淆我用XXXXXXXX“模糊”了IP地址。
这样做的正确方法是什么?
我将拥有大量的数据集(如'text1','text2'...),并希望在将它们保存到HDFS之前对每个数据集执行python函数。但我希望将结果全部放在“一个”输出文件中。
非常感谢!
MG
编辑: 似乎我的最终目标并不是很清楚。我需要单独为每个文本文件应用一个函数,然后我想将输出附加到现有的输出目录。像这样:
for i in list:
text_file = sc.textFile("/user/myname/" + i)
text_file = really_cool_python_function(text_file)
text_file.saveAsTextFile("/user/myname/all.txt")
答案 0 :(得分:1)
我想将此作为评论发布,但由于我没有足够的声誉,因此无法发表评论。
您必须将RDD转换为数据帧,然后以追加模式写入。要将RDD转换为数据帧,请查看以下答案:
https://stackoverflow.com/a/39705464/3287419
或者此链接http://spark.apache.org/docs/latest/sql-programming-guide.html
要在下面的附加模式中保存数据框,链接可能很有用:
http://spark.apache.org/docs/latest/sql-programming-guide.html#save-modes
这里几乎同样的问题Spark: Saving RDD in an already existing path in HDFS。但提供的答案是scala。我希望在python中也可以做类似的事情。
还有另一种(但很难看)的做法。将您的RDD转换为字符串。让结果字符串为resultString
。使用子进程将该字符串附加到目标文件,即
subprocess.call("echo "+resultString+" | hdfs dfs -appendToFile - <destination>", shell=True)
答案 1 :(得分:0)
如果文本文件都具有相同的模式,则可以使用Hive
将整个文件夹作为单个表读取,并直接写入该输出。
答案 2 :(得分:0)
我会试试这个,应该没问题:
list = ['text1.txt', 'text2.txt', 'text3.txt', 'text4.txt']
for i in list:
text_file = sc.textFile("/user/myname/" + i)
text_file.saveAsTextFile(f"/user/myname/{i}")