1. hadoop本身是用java写的,所以用java写mapreduce是比较合适的,然而hadoop提供了Streaming的方式,让很多语言可以来写mapreduce,下面就介绍如何用python写一个mapreduce程序,我们就从最简单的word count写起吧
2. word count是比较简单的,所以我们直接上代码,
3. map.py
#!/usr/bin/env python
# vim: set fileencoding=utf-8
import sys
def read_from_input(file):
for line in file:
yield line.split(' ')
def main(separator = ' '):
data = read_from_input(sys.stdin)
for words in data:
for word in words:
# write to the reduce
print '%s%s%d' % (word, '\t', 1)
if __name__ == '__main__':
main()
这个还是比较简单的,输入是从标准输入得到的,最后输出到reduce端是<word, 1>的形式,相当于用java写的那个context.write(key, value)
4. red.py
#!/usr/bin/env python
# vim: set fileencoding=utf-8
import sys
from itertools import groupby
from operator import itemgetter
def read_from_mapper(file, separator):
for line in file:
yield line.strip().split(separator, 2)
def main(separator = '\t'):
data = read_from_mapper(sys.stdin, separator)
for current_word, group in groupby(data, itemgetter(0)):
try:
total_count = sum(int(count) for current_word, count in group)
print "%s%s%d" % (current_word, separator, total_count)
except ValueError:
pass
if __name__ == '__main__':
main()
reduce的代码还是稍微有点复杂的,主要他不像用java写那么简便,会直接给你生成<word, list>这样的形式,所以我们就必须自己进行group,这里就用到了python的几个module:itertools和operator,既然他不给我们<word, list>的形式,那么我们就取构造这样的形式,首先输入是从map端过来的,是<word'\t'1>这样的形式,我们用yield将他们组装成generator, 然后 for current_word, group in groupby(data, itemgetter(0))是在data中进行group。key呢就是data里面项的第一个item,其实就是我们的word,最后用了一个简单的列表推导式进行统计每个word的个数,最后输出。
5. 我们需要用shell来运行他
#!/bin/bash
hadoop jar ../hadoop-streaming-2.0.0-mr1-cdh4.7.0.jar \
-input /user/xxx/output/qianjc/python/input \
-output /user/xxx/output/qianjc/python/output \
-file map.py \
-file red.py \
-mapper "python map.py" \
-reducer "python red.py" \
-jobconf mapred.reduce.tasks=1 \
-jobconf mapred.job.name="qianjc_test"
指定hadoop-streaming的jar包位置,几个参数的解释如下:
-input hdfs的输入位置
-output 结果写入hdfs的位置
-file 加载辞典,其实就是在运行的时候会将这些file拷贝到每个tasktracker的机器上
-mapper map的代码
-reducer reduce的代码
-jobconf mapred.reduce.tasks 设置reduce的个数
-jobconf mapred.job.name 设置job的名字
6. 本文主要讲了如何用python写简单mapreduce, 学会了这个处理一些简单的问题就比较迅速了,毕竟写脚本是比较快的
其实我们可以不直接在集群中运行,我们可以先看看这2个python写得对不对,我们可以这么测试:
cat xxxx.txt | ./map.py | sort | ./reduce.py,然后看输出对不对
7. 如果想了解更多hadoop streaming编程可以访问如下链接:
http://dongxicheng.org/mapreduce/hadoop-streaming-programming/
http://dongxicheng.org/mapreduce/hadoop-streaming-advanced-programming/
http://www.michael-noll.com/tutorials/writing-an-hadoop-mapreduce-program-in-python/
http://cs.smith.edu/dftwiki/index.php/Hadoop_Tutorial_2_--_Running_WordCount_in_Python