Hadoop Streaming Job在python中失败了

时间:2011-05-04 21:41:14

标签: python hadoop mapreduce

我有一个用Python编写的mapreduce作业。该程序在linux env中成功测试,但在Hadoop下运行时失败了。

这是作业命令:

hadoop  jar $HADOOP_HOME/contrib/streaming/hadoop-0.20.1+169.127-streaming.jar \
   -input /data/omni/20110115/exp6-10122 -output /home/yan/visitorpy.out \
   -mapper SessionMap.py   -reducer  SessionRed.py  -file SessionMap.py \
   -file  SessionRed.py

Session * .py的模式是755,#!/usr/bin/env python是* .py文件的顶行。 Mapper.py是:

#!/usr/bin/env python
import sys
 for line in sys.stdin:
         val=line.split("\t")
         (visidH,visidL,sessionID)=(val[4],val[5],val[108])
         print "%s%s\t%s" % (visidH,visidL,sessionID)

日志错误:

java.io.IOException: Broken pipe
    at java.io.FileOutputStream.writeBytes(Native Method)
    at java.io.FileOutputStream.write(FileOutputStream.java:260)
    at java.io.BufferedOutputStream.write(BufferedOutputStream.java:105)
    at java.io.BufferedOutputStream.flushBuffer(BufferedOutputStream.java:65)
    at java.io.BufferedOutputStream.write(BufferedOutputStream.java:109)
    at java.io.DataOutputStream.write(DataOutputStream.java:90)
    at org.apache.hadoop.streaming.io.TextInputWriter.writeUTF8(TextInputWriter.java:72)
    at org.apache.hadoop.streaming.io.TextInputWriter.writeValue(TextInputWriter.java:51)
    at org.apache.hadoop.streaming.PipeMapper.map(PipeMapper.java:110)
    at org.apache.hadoop.mapred.MapRunner.run(MapRunner.java:50)
    at org.apache.hadoop.streaming.PipeMapRunner.run(PipeMapRunner.java:36)
    at org.apache.hadoop.mapred.MapTask.runOldMapper(MapTask.java:358)
    at org.apache.hadoop.mapred.MapTask.run(MapTask.java:307)
    at org.apache.hadoop.mapred.Child.main(Child.java:170)
    at org.apache.hadoop.streaming.PipeMapper.map(PipeMapper.java:126)
    at org.apache.hadoop.mapred.MapRunner.run(MapRunner.java:50)
    at org.apache.hadoop.streaming.PipeMapRunner.run(PipeMapRunner.java:36)
    at org.apache.hadoop.mapred.MapTask.runOldMapper(MapTask.java:358)
    at org.apache.hadoop.mapred.MapTask.run(MapTask.java:307)
    at org.apache.hadoop.mapred.Child.main(Child.java:170)

8 个答案:

答案 0 :(得分:5)

我遇到了同样的问题并且想知道,因为当我测试我的mapper和reducer测试数据时,它运行了。但是当我通过hadoop map-reduce运行相同的测试集时,我常常遇到同样的问题。

如何在本地测试代码:

cat <test file> | python mapper.py | sort | python reducer.py

经过更多调查,我发现我没有在mapper.py脚本中加入'shebang line'。

#!/usr/bin/python

请将以上行添加为python脚本的第一行,并在此后留空行。

如果您需要了解更多关于'shebang line'的信息,请阅读Why do people write #!/usr/bin/env python on the first line of a Python script?

答案 1 :(得分:2)

您可以在hadoop Web界面中找到python错误消息(例如回溯)和脚本写入stderr的其他内容。它有点隐藏,但你会在流媒体为你提供的链接中找到它。您单击“映射”或“减少”,然后单击任何任务,然后在“全部”的任务日志列中

答案 2 :(得分:1)

最后我修复了错误,这是我学到的课程。 1)原始代码没有错误处理错误数据。当我在一个小数据集上测试代码时,我没有发现问题。 2)为了处理空字段/变量,我发现在Python中测试None和空字符串有点棘手。我个人喜欢功能len(strVar),它易于阅读和有效。 3)在这种情况下,hadoop命令是正确的。不知何故,带有模式644的* .py可以在我使用的环境中成功运行。

答案 3 :(得分:1)

Hadoop Streaming - Hadoop 1.0.x

我有同样的“破管”问题。问题是我的reducer中的“break”语句。所以,一切顺利,直到“休息”。之后,正在运行的减速器停止运行,打印出“Broken pipe”错误。此外,另一个减速机开始运行与前一个相同的命运。这个圈子一直在继续。

如果我理解正确,当一个reducer开始从stdin读取时(这是我的情况,在for循环中),那么它必须读取所有内容。即使你关闭stdin(os.close(0),我试过)你也不能“破坏”这个操作。

答案 4 :(得分:1)

今天我在使用Hadoop 1.0.1时遇到了同样的问题。幸运的是,我已经通过以下方式解决了这个问题:

hadoop ... -mapper $ cwd / mapper.py -reducer $ cwd / reducer.py ...

(我的Python脚本在当前目录中)。 看起来绝对路径现在是必要的。

最佳!

答案 5 :(得分:1)

脏输入可能会导致此问题。

尝试使用try {}来避免这种情况。

#!/usr/bin/env python
import sys
for line in sys.stdin:
    try:
         val=line.split("\t")
         (visidH,visidL,sessionID)=(val[4],val[5],val[108])
         print "%s%s\t%s" % (visidH,visidL,sessionID)
    except Exception  as e:
        pass

答案 6 :(得分:0)

Python + Hadoop在一些不应该的细节上是棘手的。看看here

尝试将输入路径括在双引号中。 (-input“/ data / omni / 20110115 / exp6-10122”)

答案 7 :(得分:0)

一种可能的解决方案是包括“python”,即:

-mapper  "python ./mapper.py"
-reducer "python ./reducer.py"