我想在这里找一点澄清这个问题的答案:
我的用例如下:
我有一个map-only mapreduce作业,它接受一个输入文件,进行大量的解析和修改,然后写回来.但是,某些行可能或可能不是格式不正确,如果是这种情况,我想将原始行写入单独的文件.
似乎这样做的一种方法是将文件名添加到我正在打印的行中并使用multipleOutputFormat参数.例如,如果我原来有:
if line_is_valid(line):
print name + '\t' + comments
Run Code Online (Sandbox Code Playgroud)
我可以这样做:
if line_is_valid(line):
print valid_file_name + '\t' + name + '\t' + comments
else:
print err_file_name + '\t' + line
Run Code Online (Sandbox Code Playgroud)
我对此解决方案的唯一问题是我不希望file_name显示为文本文件中的第一列.我想我可以再运行另一个工作去除每个文件的第一列,但这看起来有点傻.所以:
1)这是使用python mapreduce作业管理多个输出文件的正确方法吗?
2)摆脱初始列的最佳方法是什么?
SSa*_*ker 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;
}
}
Run Code Online (Sandbox Code Playgroud)
编译步骤:
当您在上面保存的文件所在的目录中时,键入 -
$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
执行这些操作后,您应该在输出路径中看到两个目录,一个带有valid_file_name,另一个带有err_file_name.所有将valid_file_name作为标记的记录将转到valid_file_name目录,所有具有err_file_name的记录将转到err_file_name目录.
我希望所有这些都有道理.