热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

python写mappreduce

python写mr比java要省事的多下面介绍个简单的例子这个就是要的mapperimportsys,urlparse,osfromsubscribe_cleani

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}_xiaofei.weng -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

#include

#include

?

#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

#include

#include

?

#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

#include

#include


using namespace std;

?


int main(){


????????string key;


????????string value = "1";


????????while(cin>>key){


????????????????cout<"\t"<


????????}


????????return 0;

}

//------------------------------------------------------------------------------------------------------------

//reducer

#include

#include

#include

#include


using namespace std;


int main(){


????????string key;


????????string value;


????????mapint> word2count;


????????mapint>::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<first<<"\t"<second<


????????}


????????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多线程详解与示例
    本文介绍了Python中的多线程编程,包括僵尸进程和孤儿进程的概念,并提供了具体的代码示例。同时,详细解释了0号进程和1号进程在系统中的作用。 ... [详细]
  • Java EE 平台集成了多种服务、API 和协议,旨在支持基于 Web 的多层应用程序开发。本文将详细介绍 Java EE 中的 13 种关键技术规范,帮助开发者更好地理解和应用这些技术。 ... [详细]
  • JavaSE For循环入门示例
    本文将介绍Java中For循环的基本概念和使用方法,通过几个简单的示例帮助初学者更好地理解和掌握For循环。 ... [详细]
  • iOS snow animation
    CTSnowAnimationView.hCTMyCtripCreatedbyalexon1614.Copyright©2016年ctrip.Allrightsreserved.# ... [详细]
  • packagecom.panchan.tsmese.utils;importjava.lang.reflect.ParameterizedType;importjava.lang. ... [详细]
  • 蒜头君的倒水问题(矩阵快速幂优化)
    蒜头君将两杯热水分别倒入两个杯子中,每杯水的初始量分别为a毫升和b毫升。为了使水冷却,蒜头君采用了一种特殊的方式,即每次将第一杯中的x%的水倒入第二杯,同时将第二杯中的y%的水倒入第一杯。这种操作会重复进行k次,最终求出两杯水中各自的水量。 ... [详细]
  • malloc 是 C 语言中的一个标准库函数,全称为 memory allocation,即动态内存分配。它用于在程序运行时申请一块指定大小的连续内存区域,并返回该区域的起始地址。当无法预先确定内存的具体位置时,可以通过 malloc 动态分配内存。 ... [详细]
  • NX二次开发:UFUN点收集器UF_UI_select_point_collection详解
    本文介绍了如何在NX中使用UFUN库进行点收集器的二次开发,包括必要的头文件包含、初始化和选择点集合的具体实现。 ... [详细]
  • 本文章提供了适用于 Cacti 的多核 CPU 监控模板,支持 2、4、8、12、16、24 和 32 核配置。请注意,0.87g 版本的 Cacti 需要手动修改哈希值为 0021 才能使用,而 0.88 及以上版本则可直接导入。 ... [详细]
  • 本文介绍了一种支付平台异步风控系统的架构模型,旨在为开发类似系统的工程师提供参考。 ... [详细]
  • 使用 Git Rebase -i 合并多个提交
    在开发过程中,频繁的小改动往往会生成多个提交记录。为了保持代码仓库的整洁,我们可以使用 git rebase -i 命令将多个提交合并成一个。 ... [详细]
  • Manacher算法详解:寻找最长回文子串
    本文将详细介绍Manacher算法,该算法用于高效地找到字符串中的最长回文子串。通过在字符间插入特殊符号,Manacher算法能够同时处理奇数和偶数长度的回文子串问题。 ... [详细]
  • 本文介绍了多种开源数据库及其核心数据结构和算法,包括MySQL的B+树、MVCC和WAL,MongoDB的tokuDB和cola,boltDB的追加仅树和mmap,levelDB的LSM树,以及内存缓存中的一致性哈希。 ... [详细]
  • 本文详细介绍了Linux系统中用于管理IPC(Inter-Process Communication)资源的两个重要命令:ipcs和ipcrm。通过这些命令,用户可以查看和删除系统中的消息队列、共享内存和信号量。 ... [详细]
  • A*算法在AI路径规划中的应用
    路径规划算法用于在地图上找到从起点到终点的最佳路径,特别是在存在障碍物的情况下。A*算法是一种高效且广泛使用的路径规划算法,适用于静态和动态环境。 ... [详细]
author-avatar
平平您好
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有