设为首页 收藏本站
查看: 898|回复: 0

[经验分享] python写mappreduce

[复制链接]

尚未签到

发表于 2017-4-23 15:02:56 | 显示全部楼层 |阅读模式
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


 

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-368281-1-1.html 上篇帖子: Python隐藏功能 下篇帖子: Programming Python到了
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表