python写mr比java要省事的多
下面介绍个简单的例子
这个就是要的mapper
import sys,urlparse,os from subscribe_clean import * from subscribe_ad import * clean=subScribeClean(subscribeMonitorCompany()) for line in sys.stdin: try: rs = clean.analyzeData(line) if rs==None or len(rs)<=0: continue print '%s' % (clean.cvtToStr(rs)) except Exception as e: continue
在运行时,用hadoop streaming
hadoop jar /home/q/hadoop/hadoop-2.2.0/share/hadoop/tools/lib/hadoop-streaming-2.2.0.jar \ -D mapred.reduce.tasks=0 \ -D mapred.job.queue.name=wirelessdev \ -D mapred.job.name=logclean_hoteltts_${log_day}_dirk.zhang\ -D mapred.child.java.opts=-Xmx8000m -D mapred.min.split.size=6291456 -D mapred.max.split.size=6291456 -D mapreduce.map.memory.mb=8192 -D mapreduce.map.java.opts='-Xmx8000M' -D mapred.child.map.java.opts='-Xmx8000M' \ -D mapred.output.compress=true -D mapred.output.compression.codec=org.apache.hadoop.io.compress.GzipCodec -D mapred.output.compression.type=BLOCK \ -file sub_mc_clean_mapper.py \ -input ${hdfs_path2} \ -output ${hive_path2} \ -mapper sub_mc_clean_mapper.py \
在用python输出时,经常出现输出多了空行,这样将生成的文件导入hive,会报错,需要在输出的时候加上
strip()函数
转一个n人的帖子:
http://dongxicheng.org/mapreduce/hadoop-streaming-programming/
1、概述
Hadoop Streaming是Hadoop提供的一个编程工具,它允许用户使用任何可执行文件或者脚本文件作为Mapper和Reducer,例如:
采用shell脚本语言中的一些命令作为mapper和reducer(cat作为mapper,wc作为reducer)
$HADOOP_HOME/bin/hadoop jar $HADOOP_HOME/contrib/streaming/hadoop-*-streaming.jar \
-input myInputDirs \
-output myOutputDir \
-mapper cat \
-reducer wc
本文安排如下,第二节介绍Hadoop Streaming的原理,第三节介绍Hadoop Streaming的使用方法,第四节介绍Hadoop Streaming的程序编写方法,在这一节中,用C++、C、shell脚本 和python实现了WordCount作业,第五节总结了常见的问题。文章最后给出了程序下载地址。(本文内容基于Hadoop-0.20.2版本)
(注:如果你采用的语言为C或者C++,也可以使用Hadoop Pipes,具体可参考这篇文章:Hadoop Pipes编程。)
关于Hadoop Streaming高级编程方法,可参考这篇文章:Hadoop Streaming高级编程,Hadoop编程实例。
2、Hadoop Streaming原理
mapper和reducer会从标准输入中读取用户数据,一行一行处理后发送给标准输出。Streaming工具会创建MapReduce作业,发送给各个tasktracker,同时监控整个作业的执行过程。
如果一个文件(可执行或者脚本)作为mapper,mapper初始化时,每一个mapper任务会把该文件作为一个单独进程启动,mapper任务运行时,它把输入切分成行并把每一行提供给可执行文件进程的标准输入。 同时,mapper收集可执行文件进程标准输出的内容,并把收到的每一行内容转化成key/value对,作为mapper的输出。 默认情况下,一行中第一个tab之前的部分作为key,之后的(不包括tab)作为value。如果没有tab,整行作为key值,value值为null。
对于reducer,类似。
以上是Map/Reduce框架和streaming mapper/reducer之间的基本通信协议。
3、Hadoop Streaming用法
Usage: $HADOOP_HOME/bin/hadoop jar \
$HADOOP_HOME/contrib/streaming/hadoop-*-streaming.jar [options]
options:
(1)-input:输入文件路径
(2)-output:输出文件路径
(3)-mapper:用户自己写的mapper程序,可以是可执行文件或者脚本
(4)-reducer:用户自己写的reducer程序,可以是可执行文件或者脚本
(5)-file:打包文件到提交的作业中,可以是mapper或者reducer要用的输入文件,如配置文件,字典等。
(6)-partitioner:用户自定义的partitioner程序
(7)-combiner:用户自定义的combiner程序(必须用java实现)
(8)-D:作业的一些属性(以前用的是-jonconf),具体有:
1)mapred.map.tasks:map task数目
2)mapred.reduce.tasks:reduce task数目
3)stream.map.input.field.separator/stream.map.output.field.separator: map task输入/输出数
据的分隔符,默认均为\t。
4)stream.num.map.output.key.fields:指定map task输出记录中key所占的域数目
5)stream.reduce.input.field.separator/stream.reduce.output.field.separator:reduce task输入/输出数据的分隔符,默认均为\t。
6)stream.num.reduce.output.key.fields:指定reduce task输出记录中key所占的域数目
另外,Hadoop本身还自带一些好用的Mapper和Reducer:
(1) Hadoop聚集功能
Aggregate提供一个特殊的reducer类和一个特殊的combiner类,并且有一系列的“聚合器”(例如“sum”,“max”,“min”等)用于聚合一组value的序列。用户可以使用Aggregate定义一个mapper插件类,这个类用于为mapper输入的每个key/value对产生“可聚合项”。Combiner/reducer利用适当的聚合器聚合这些可聚合项。要使用Aggregate,只需指定“-reducer aggregate”。
(2)字段的选取(类似于Unix中的‘cut’)
Hadoop的工具类org.apache.hadoop.mapred.lib.FieldSelectionMapReduc帮助用户高效处理文本数据,就像unix中的“cut”工具。工具类中的map函数把输入的key/value对看作字段的列表。 用户可以指定字段的分隔符(默认是tab),可以选择字段列表中任意一段(由列表中一个或多个字段组成)作为map输出的key或者value。 同样,工具类中的reduce函数也把输入的key/value对看作字段的列表,用户可以选取任意一段作为reduce输出的key或value。
4、Mapper和Reducer实现
本节试图用尽可能多的语言编写Mapper和Reducer,包括Java,C,C++,Shell脚本,python等(初学者运行第一个程序时,务必要阅读第5部分 “常见问题及解决方案”!!!!)。
由于Hadoop会自动解析数据文件到Mapper或者Reducer的标准输入中,以供它们读取使用,所有应先了解各个语言获取标准输入的方法。
(1) Java语言:
见Hadoop自带例子
(2) C++语言:
1
2
3
4
5
|
string key; while (cin>>key){
cin>>value;
….
} |
(3) C语言:
1
2
3
4
5
|
char buffer[BUF_SIZE];
while ( fgets (buffer, BUF_SIZE - 1, stdin)){
int len = strlen (buffer);
…
} |
(4) Shell脚本
管道
(5) Python脚本
1
2
3
|
import sys
for line in sys.stdin:
....... |
为了说明各种语言编写Hadoop Streaming程序的方法,下面以WordCount为例,WordCount作业的主要功能是对用户输入的数据中所有字符串进行计数。
(1)C语言实现
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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
|
//mapper #include <stdio.h> #include <string.h> #include <stdlib.h> #define BUF_SIZE 2048 #define DELIM "\n" int main( int argc, char *argv[]){
char buffer[BUF_SIZE];
while ( fgets (buffer, BUF_SIZE - 1, stdin)){
int len = strlen (buffer);
if (buffer[len-1] == '\n' )
buffer[len-1] = 0;
char *querys = index(buffer, ' ' );
char *query = NULL;
if (querys == NULL) continue ;
querys += 1; /* not to include '\t' */
query = strtok (buffer, " " );
while (query){
printf ( "%s\t1\n" , query);
query = strtok (NULL, " " );
}
}
return 0;
} //--------------------------------------------------------------------------------------- //reducer #include <stdio.h> #include <string.h> #include <stdlib.h> #define BUFFER_SIZE 1024 #define DELIM "\t" int main( int argc, char *argv[]){
char strLastKey[BUFFER_SIZE];
char strLine[BUFFER_SIZE];
int count = 0;
*strLastKey = '\0' ;
*strLine = '\0' ;
while ( fgets (strLine, BUFFER_SIZE - 1, stdin) ){
char *strCurrKey = NULL;
char *strCurrNum = NULL;
strCurrKey = strtok (strLine, DELIM);
strCurrNum = strtok (NULL, DELIM); /* necessary to check error but.... */
if ( strLastKey[0] == '\0' ){
strcpy (strLastKey, strCurrKey);
}
if ( strcmp (strCurrKey, strLastKey)) {
printf ( "%s\t%d\n" , strLastKey, count);
count = atoi (strCurrNum);
} else {
count += atoi (strCurrNum);
}
strcpy (strLastKey, strCurrKey);
}
printf ( "%s\t%d\n" , strLastKey, count); /* flush the count */
return 0;
} |
(2)C++语言实现
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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
|
//mapper #include <stdio.h> #include <string> #include <iostream> using namespace std;
int main(){
string key;
string value = "1" ;
while (cin>>key){
cout<<key<< "\t" <<value<<endl;
}
return 0;
} //------------------------------------------------------------------------------------------------------------ //reducer #include <string> #include <map> #include <iostream> #include <iterator> using namespace std;
int main(){
string key;
string value;
map<string, int > word2count;
map<string, int >::iterator it;
while (cin>>key){
cin>>value;
it = word2count.find(key);
if (it != word2count.end()){
(it->second)++;
}
else {
word2count.insert(make_pair(key, 1));
}
}
for (it = word2count.begin(); it != word2count.end(); ++it){
cout<<it->first<< "\t" <<it->second<<endl;
}
return 0;
} |
(3)shell脚本语言实现
简约版,每行一个单词:
1
2
3
4
5
|
$HADOOP_HOME /bin/hadoop jar $HADOOP_HOME /hadoop-streaming .jar \
-input myInputDirs \
-output myOutputDir \
-mapper cat \
-reducer wc
|
详细版,每行可有多个单词(由史江明编写): mapper.sh
1
2
3
4
5
6
7
|
#! /bin/bash while read LINE; do
for word in $LINE
do
echo "$word 1"
done
done |
reducer.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
#! /bin/bash count=0 started=0 word= ""
while read LINE; do
newword=` echo $LINE | cut -d ' ' -f 1`
if [ "$word" != "$newword" ]; then
[ $started - ne 0 ] && echo "$word\t$count"
word=$newword
count=1
started=1
else
count=$(( $count + 1 ))
fi
done echo "$word\t$count"
|
(4)Python脚本语言实现
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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
|
#!/usr/bin/env python import sys
# maps words to their counts word2count = {}
# input comes from STDIN (standard input) for line in sys.stdin:
# remove leading and trailing whitespace
line = line.strip()
# split the line into words while removing any empty strings
words = filter ( lambda word: word, line.split())
# increase counters
for word in words:
# write the results to STDOUT (standard output);
# what we output here will be the input for the
# Reduce step, i.e. the input for reducer.py
#
# tab-delimited; the trivial word count is 1
print '%s\t%s' % (word, 1 )
#--------------------------------------------------------------------------------------------------------- #!/usr/bin/env python from operator import itemgetter
import sys
# maps words to their counts word2count = {}
# input comes from STDIN for line in sys.stdin:
# remove leading and trailing whitespace
line = line.strip()
# parse the input we got from mapper.py
word, count = line.split()
# convert count (currently a string) to int
try :
count = int (count)
word2count[word] = word2count.get(word, 0 ) + count
except ValueError:
# count was not a number, so silently
# ignore/discard this line
pass
# sort the words lexigraphically; # # this step is NOT required, we just do it so that our # final output will look more like the official Hadoop # word count examples sorted_word2count = sorted (word2count.items(), key = itemgetter( 0 ))
# write the results to STDOUT (standard output) for word, count in sorted_word2count:
print '%s\t%s' % (word, count)
|
5、常见问题及解决方案
(1)作业总是运行失败,
提示找不多执行程序, 比如“Caused by: java.io.IOException: Cannot run program “/user/hadoop/Mapper”: error=2, No such file or directory”:
可在提交作业时,采用-file选项指定这些文件, 比如上面例子中,可以使用“-file Mapper -file Reducer” 或者 “-file Mapper.py -file Reducer.py”, 这样,Hadoop会将这两个文件自动分发到各个节点上,比如:
$HADOOP_HOME/bin/hadoop jar $HADOOP_HOME/contrib/streaming/hadoop-*-streaming.jar \
-input myInputDirs \
-output myOutputDir \
-mapper Mapper.py\
-reducer Reducerr.py\
-file Mapper.py \
-file Reducer.py
(2)用脚本编写时,第一行需注明脚本解释器,默认是shell (3)如何对Hadoop Streaming程序进行测试? Hadoop Streaming程序的一个优点是易于测试,比如在Wordcount例子中,可以运行以下命令在本地进行测试:
cat input.txt | python Mapper.py | sort | python Reducer.py
或者
cat input.txt | ./Mapper | sort | ./Reducer
相关推荐
python读写excel
基于python写的春节烟花源码+注释.zip基于python写的春节烟花源码+注释.zip基于python写的春节烟花源码+注释.zip基于python写的春节烟花源码+注释.zip基于python写的春节烟花源码+注释.zip基于python写的春节烟花...
Python写了一个词达人半自动答题工具源码 Python写了一个词达人半自动答题工具源码 Python写了一个词达人半自动答题工具源码 Python写了一个词达人半自动答题工具源码 Python写了一个词达人半自动答题工具源码 ...
用python写的图片批量转pdf工具用python写的图片批量转pdf工具用python写的图片批量转pdf工具用python写的图片批量转pdf工具用python写的图片批量转pdf工具用python写的图片批量转pdf工具用python写的图片批量转pdf...
运用python写个二维码
《用Python写网络爬虫》讲解了如何使用Python来编写网络爬虫程序,内容包括网络爬虫简介,从页面中抓取数据的三种方法,提取缓存中的数据,使用多个线程和进程来进行并发抓取,如何抓取动态页面中的内容,与表单进行...
python读写MySQL数据库操作,读操作,写操作,python读写MySQL数据库操作
python 使用 snap7 实现西门子 plc 1200的读写 地址读写
在IT行业中,编程语言Python因其简洁明了的语法和丰富的库支持而被广泛应用于各种领域,包括数据分析、机器学习、Web开发等。本项目利用Python编写了一个比赛抽签软件,旨在帮助组织者轻松进行随机抽签操作,确保...
使用python写的毕业设计,毕业生反馈与分析系统.zip使用python写的毕业设计,毕业生反馈与分析系统.zip使用python写的毕业设计,毕业生反馈与分析系统.zip使用python写的毕业设计,毕业生反馈与分析系统.zip使用...
python读写mdb、读excel的ui界面的完整源代码、mdb测试文件和excel测试文件和exe文件,使用Qt Designer产生ui文件,源代码用到了多线程、自定义信号和槽(slot)函数,两个文件打开对话框用来选择mdb文件和excel文件,...
这是由Python写的网站源码,采用了Python里最强大的后端框架Django,该网站所实现的功能是为旅游者提供乡间小屋预订、租住服务,对希望学习利用Python+Django进行网站建设的开发者而言是一个难得的示例。
《用Python写网络爬虫》讲解了如何使用Python来编写网络爬虫程序,内容包括网络爬虫简介,从页面中抓取数据的三种方法,提取缓存中的数据,使用多个线程和进程来进行并发抓取,如何抓取动态页面中的内容,与表单进行...
初学python 分享一个小程序:python 如何写入TXT文件!
自己整理的,用python写xml文件,还算比较全面,唯一的缺点就是不知道如何把有text的节点整在同一行
python写的窗口
用python写的简单投篮游戏(源码),很好的资源! 用python写的简单投篮游戏(源码),很好的资源! 用python写的简单投篮游戏(源码),很好的资源! 用python写的简单投篮游戏(源码),很好的资源! 用python写的...
python写的一个简单的web server,计算机网路课堂研讨要求实现的,哈哈
标题中的“python写的小东西”很可能是指一个使用Python编程语言编写的小型应用程序或脚本。Python因其简洁明了的语法和强大的功能而受到广大程序员的喜爱,尤其适合开发各种实用工具和小型项目。在这个场景中,可能...
python写的快速搭建qt(cpp)的基于qmake的脚手架脚本,非pyqt(源码) python写的快速搭建qt(cpp)的基于qmake的脚手架脚本,非pyqt(源码) python写的快速搭建qt(cpp)的基于qmake的脚手架脚本,非pyqt(源码) python写的...