用python写_菜鸟世界 -用python 写mapreduce程序

使用python写一个mapreduce程序,来统计一个文件中的单词出现的个数

1、创建示例文件  words

python|thread|process

python|xlrd|pyinotiy

python|print|c++

c++|java|php

node.js|javascript|go

将文件上传至hsdf上 执行命令 hadoop fs -put words /user/hive/warehouse/test.db/zds

你也许会质疑,这么简单的工作何须使用mapreduce呢,没错,如果一个文件里只有这么一丁点数据,确实没有必要使用mapreduce来处理,但这毕竟只是一个实例,假设这个文件有几个T那么大,你还能用单机的程序进行处理么,不论是空间还是时间,都是无法承受的,

2、编写mapper文件

新建文件 mapper.py 内容为

# coding=utf-8

import sys

for line in sys.stdin:

words = line.strip().split('|')

for word in words:

print word

这里的关键是使用 HadoopStreaming 来让数据在map 和 reduce之间传递数据,使用sys.stdin获得输入数据,而print 等同于 sys.stdout ,作为标准输出

这段代码的作用是一行一行的读取数据,然后用竖线分割,在逐个输出

2.2 测试mapper

执行命令 cat words | python mapper.py ,words 是本地文件,我现在本地进行测试,确保程序是没有明显bug的,免得在hadoop集群上运行程序时出错,毕竟那是要占用集群资源的,有问题要提前发现

3、编写reducer.py

# coding=utf-8

import sys

def get_count():

first_flag = 0

count = 0

for line in sys.stdin:

word = line.strip()

if first_flag == 0:

first_flag = 1

old_key = word

if old_key != word:

print "{word}\t{count}".format(word=old_key, count=count)

# 复位

old_key = word

count = 0

count += 1

if first_flag == 1:

print "{word}\t{count}".format(word=old_key, count=count)

if __name__ == '__main__':

get_count()

需要明确一点,hadoop框架会自动的将相同的key分配到同一个reducer上,这个key,默认的就是上一个mapper输出数据的以\t,或者\001分割后的第一部分,我写的mapper中,直接输出了word,那么,这些单词就成为key

程序中有一个old_key变量,不同的key的数据会被分到同一个reducer上,因此,程序需要识别出不同的key,来进行计数 ,此外还要注意不要忘记最后一个key的处理

执行命令 cat words | python mapper.py |sort|python reducer.py

输出结果为

c++ 2

go 1

java 1

javascript 1

node.js 1

php 1

print 1

process 1

pyinotiy 1

python 3

thread 1

xlrd 1

至此,程序已经可以正常运行,但是reducer的程序非常不符合python的精神,苦涩难懂,我要对它进行一番修改

# coding=utf-8

import sys

from operator import itemgetter

from itertools import groupby

def read_mapper_output(files, separator='\t'):

for line in files:

yield line.strip().split(separator, 1)

def main():

data = read_mapper_output(sys.stdin)

for key, data in groupby(data, itemgetter(0)):

count = 0

for value in data:

count += 1

print "{word}\t{count}".format(word=key, count=count)

if __name__ == '__main__':

main()

这样修改后,看起来简洁了许多,不过如果你没有很深的python基础功底,可能更难看得懂

4、 在hadoop集群上运行代码

编写run.sh脚本

#!/bin/bash/

(1) hadoop fs -rm -r -f /user/hive/warehouse/test_tmp.db/zds/wordcount

(2) hadoop jar /opt/lib/hadoop-mapreduce/hadoop-streaming.jar \

(3) -libjars /opt/lib/hive/lib/hive-exec-1.1.0-cdh5.4.8.jar \

(4) -jobconf mapreduce.reduce.shuffle.memory.limit.percent=0.1 \

(5) -jobconf mapreduce.reduce.shuffle.input.buffer.percent=0.3 \

(6) -jobconf mapreduce.map.memory.mb=512 \

(7) -jobconf mapreduce.reduce.memory.mb=512 \

(8) -jobconf mapred.map.capacity=100 \

(9) -jobconf mapred.reduce.capacity=100 \

(10) -jobconf mapred.job.name=test_word_count \

(11) -file mapper.py \

(12) -file reducer.py \

(13) -mapper "python mapper.py" \

(14) -reducer "python reducer.py" \

(15) -input /user/hive/warehouse/test_tmp.db/zds/words \

(16) -output /user/hive/warehouse/test_tmp.db/zds/wordcount \

先看16,规定了输出,而1 呢,则是删除文件,不然第二次运行的时候,由于文件存在会终止运行

2 是指定 hadoop-streaming.jar,具体的位置,要根据你自己机器上的位置而定

3 是指定 libjars ,具体的也要根据你机器上的位置而定

4 到10 指定了运行时的各项参数

11 ,12 指定了要分发到集群上的文件

13,14 指定了mapper和reduce 要运行的程序

15 指定了输入文件

执行结束后,将文件从hadoop上下载下来

hadoop fs -getmerge /user/hive/warehouse/test_tmp/zds/wordcount wordcount

cat wordcount 内容为

xlrd 1

print 1

python 3

javascript 1

process 1

c++ 2

pyinotiy 1

java 1

php 1

go 1

thread 1

node.js 1

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值