我正在寻找关于这个问题的答案的一点澄清:
Generating Separate Output files in Hadoop Streaming
我的用例如下:
我有一个map-only mapreduce作业,它接受一个输入文件,进行大量的解析和修改,然后写回来。但是,某些行可能格式不正确,如果是这种情况,我想将原始行写入单独的文件。
似乎这样做的一种方法是将文件名添加到我正在打印的行中并使用multipleOutputFormat参数。例如,如果我最初有:
if line_is_valid(line):
print name + '\t' + comments
我可以改为:
if line_is_valid(line):
print valid_file_name + '\t' + name + '\t' + comments
else:
print err_file_name + '\t' + line
我对此解决方案的唯一问题是我不希望file_name显示为文本文件中的第一列。我想我可以再运行另一个工作去除每个文件的第一列,但这看起来有点傻。所以:
1)这是使用python mapreduce作业管理多个输出文件的正确方法吗?
2)摆脱初始列的最佳方法是什么?
答案 0 :(得分:18)
您可以执行以下操作,但它涉及一些Java编译,我认为这不应该是一个问题,如果您希望使用Python完成您的用例 - 从Python中,据我所知,不能直接从最终输出中跳过文件名,就像你的用例在单个作业中所要求的那样。但是下面显示的内容可以轻松实现!
这是需要编译的Java类 -
package com.custom;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapred.lib.MultipleTextOutputFormat;
public class CustomMultiOutputFormat extends MultipleTextOutputFormat<Text, Text> {
/**
* Use they key as part of the path for the final output file.
*/
@Override
protected String generateFileNameForKeyValue(Text key, Text value, String leaf) {
return new Path(key.toString(), leaf).toString();
}
/**
* We discard the key as per your requirement
*/
@Override
protected Text generateActualKey(Text key, Text value) {
return null;
}
}
编译步骤:
当您位于上述保存文件所在的目录中时,请键入 -
$JAVA_HOME/bin/javac -cp $(hadoop classpath) -d . CustomMultiOutputFormat.java
确保在尝试之前将JAVA_HOME设置为/ path / to / your / SUNJDK 上面的命令。
使用(完全输入) -
制作custom.jar文件 $JAVA_HOME/bin/jar cvf custom.jar com/custom/CustomMultiOutputFormat.class
最后,像 -
一样开展工作 hadoop jar /path/to/your/hadoop-streaming-*.jar -libjars custom.jar -outputformat com.custom.CustomMultiOutputFormat -file your_script.py -input inputpath --numReduceTasks 0 -output outputpath -mapper your_script.py
执行这些操作后,您应该会在 outputpath 中看到两个目录,其中 valid_file_name ,另一个目录 err_file_name 。所有将valid_file_name作为标记的记录将转到valid_file_name目录,所有具有err_file_name的记录将转到err_file_name目录。
我希望所有这些都有道理。