Hadoop Streaming导入自定义module
问题
今天发现用Python
编写Hadoop Streaming
脚本时,如果自己导入自定义的模块会报错-_-
列如word count
中的reducer程序:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25#!/usr/bin/env python
#-*- coding=utf8 -*-
import sys
import utils_helper
lastk = None #这里标志最后一个k 用于控制同一个key 到一个组中
count = 0
for line in sys.stdin:
w,c = line.split('\t')
c = int(c) #不转成int会比较麻烦 这是是计数
if lastk == None: #这里是判断是否过来的是第一个key
lastk=w
count = utils_helper.add(count,c)
elif lastk == w:
count += c
else:
print "%s\t%s"%(lastk,count)
lastk=w
count = c #这里重置计数
if lastk is not None:
print "%s\t%s"%(lastk,count)
故意使用一个自定义模块来测试utils_helper.py
1
2
3
4#! /usr/bin/env python
def add(x,y):
return x+y
如果本地跑起来是(就是本地DEBUG)就可以正常跑的,但是放到Hadoop
集群上跑的时候,使用的启动命令为:
hadoop jar $HADOOP_HOME/share/hadoop/tools/lib/hadoop-streaming-2.7.0.jar \
-input /yyl/data/line.txt \
-output /yyl/test/ouput/streaming2 \
-mapper "python word_count_mapper.py" \
-reducer "python word_count_reducer.py" \
-file $HADOOP_HOME/runjar/pyscript/word_count_mapper.py \
-file $HADOOP_HOME/runjar/pyscript/word_count_reducer.py \
-file $HADOOP_HOME/runjar/pyscript/utils_helper.py \
可以发现跑到reducer
阶段时会报错:
16/03/24 12:11:40 INFO mapreduce.Job: Running job: job_1458827745768_0018
16/03/24 12:11:53 INFO mapreduce.Job: Job job_1458827745768_0018 running in uber mode : false
16/03/24 12:11:53 INFO mapreduce.Job: map 0% reduce 0%
16/03/24 12:12:12 INFO mapreduce.Job: map 100% reduce 0%
16/03/24 12:12:22 INFO mapreduce.Job: Task Id : attempt_1458827745768_0018_r_000000_0, Status : FAILED
Error: java.lang.RuntimeException: PipeMapRed.waitOutputThreads(): subprocess failed with code 2
at org.apache.hadoop.streaming.PipeMapRed.waitOutputThreads(PipeMapRed.java:322)
at org.apache.hadoop.streaming.PipeMapRed.mapRedFinished(PipeMapRed.java:535)
at org.apache.hadoop.streaming.PipeReducer.close(PipeReducer.java:134)
at org.apache.hadoop.io.IOUtils.cleanup(IOUtils.java:244)
at org.apache.hadoop.mapred.ReduceTask.runOldReducer(ReduceTask.java:459)
at org.apache.hadoop.mapred.ReduceTask.run(ReduceTask.java:392)
at org.apache.hadoop.mapred.YarnChild$2.run(YarnChild.java:163)
at java.security.AccessController.doPrivileged(Native Method)
at javax.security.auth.Subject.doAs(Subject.java:415)
at org.apache.hadoop.security.UserGroupInformation.doAs(UserGroupInformation.java:1657)
at org.apache.hadoop.mapred.YarnChild.main(YarnChild.java:158)
这就疼了,代码应该没问题呀,尝试了好几遍之后还是这个错误。。。-_-!!
解决方案
后来在stackoverflow
发现有人问了同样的问题,并且我使用其中一个方案解决了:
When Hadoop-Streaming starts the python scripts, your python script's path is where the script file really is. However, hadoop starts them at './', and your lib.py(it's a symlink) is at './', too. So, try to add 'sys.path.append("./")' before you import lib.py like this:
import sys
sys.path.append('./')
import lib
lib.py
表示自定义包
应该就是-file
上传到计算机器之后文件路径的问题产生的,不过感觉他的理由有点疑惑,按他说的如果我上传之后会通过软连接组织到同一目录下再使用,所以如果直接导入包可能会出问题,那我如果上传之前就是在同一目录下应该就不会出问题吧??这里并不是很理解,但是至少是导入包的问题是解决了^_^
参考
本作品采用[知识共享署名-非商业性使用-相同方式共享 2.5]中国大陆许可协议进行许可,我的博客欢迎复制共享,但在同时,希望保留我的署名权kubiCode,并且,不得用于商业用途。如您有任何疑问或者授权方面的协商,请给我留言。