小言_互联网的博客

Python带你聊天式走完Hadoop之MapReduce——史上最详细的操作步骤【内附hdfs操作合集】

261人阅读  评论(0)

目录

一本正经的介绍😎

背景介绍

前期准备

Python 的 MapReduce 代码

Map: mapper.py

详细步骤(小学生也可以完成的步骤!)

聊天式教学:(🐰小W——>👸小L)的对话

🐰小W:把大象装进冰箱需要几步?

一、打开冰箱

mapper.py

reducer.py

二、把大象装进冰箱

测试脚本代码

测试结束,集群运行!

三、关闭冰箱

hdfs语法合集

加餐案例😉

每文一语


 


一本正经的介绍😎

背景介绍

在这个实例中, 主要是介绍如何使用 Python 为 Hadoop 编写一个简单的MapReduce 程序。尽管 Hadoop 框架是使用 Java 编写的但是我们仍然希望能够使用像 C++、Python 等语言来实现 Hadoop 程序。

因为 Hadoop 官方网站给的示例程序是使用Jython 编写并打包成 Jar 文件,这样显然给未学习过 java 语言的开发人员造成不便, 而且, Hadoop 本身具有很好的跨平台特性, 所以我们可以使用 Python等其他一些常用平台与 Hadoop 关联进行编程, 首先要确认我们需要做的工作。

我们将编写一个简单的 MapReduce 程序,使用的是 C-Python,而不是Jython 编写后打包成 jar 包的程序。这个例子就是要实现 WordCount 并且通过使用 Python 来实现,例子通过读取文本文件来统计出单词的出现次数。结果也以文本形式输出,每一行包含一个单词和单词出现的次数,两者中间使用制表符来进行间隔。

前期准备

编写这个程序之前,你学要架设好 Hadoop 集群,这样才能不会在后期工作难受,如果是使用的是学校的机房,请按照这个步骤,直接暴力复制,一点都不需要改动,也可以直接运行!

Python 的 MapReduce 代码

使用 Python 编写 MapReduce 代码的技巧就在于我们使用了 HadoopStreaming来帮助我们在 Map 和 Reduce 间通过 STDIN (标准输入)和 STDOUT (标准输出)来传递数据.我们使用 Python 的 sys.stdin 来输入数据,使用 sys.stdout 输出数据,这样做是因为 HadoopStreaming 会帮我们办好其他事。

Map: mapper.py

将写好的代码保存在/usr/local/hadoop/mapper.py 中,他将从 STDIN 读取数据并将单词成行分隔开,生成一个列表映射单词与发生次数的关系:注意:要确保这个脚本有足够权限(chmod +x mapper.py)。
 


详细步骤(小学生也可以完成的步骤!)

感觉好枯燥啊,这么多的文字,绝望了,就知道感觉到绝望了哈

 

聊天式教学:(🐰小W——>👸小L)的对话

 

🐰小W:把大象装进冰箱需要几步?

👸小L:不是三步吗,这么简单的问题还想要考我

🐰小W:哈哈哈,真聪明哟,三步带你感受编程的快乐哈

 

一、打开冰箱

🐰小W:打开我们的虚拟机,点击图标,然后点击hadoopvm,进入我们的另外一台机器

输入密码:hadoop

👸小L:好了,但是这个虚拟机的桌面也太小了吧,看的我眼睛都哭了😩

🐰小W:怎么会很小了,看看下面的操作,瞬间变大!

点击这里进入全屏模式

 

🐰小W:然后准备好我们的mapper.py和reducer.py代码

👸小L:这个我知道,不就是创建两个文件夹吗,看我操作:

首先在Windows桌面新建两个文件,因为Windows使用起来非常方便,写好之后就可以直接复制到Ubuntu里面了,这样是最方便的哟,哈哈哈

🐰小W:不是的,这样做就错啦,而且错的让你无法相信这个世界还有真理!!!哈哈哈

因为:在win下编辑的时候,换行结尾是\n\r , 而在linux下 是\n,所以才会有 多出来的\r

sed -i 's/\r$//' build.sh 

要记住哟,在Linux和Windows一些文件的操作是不一样的,两个操作系统有各自的规则,并不是在Windows下面方便操作,就可以操作哈

🐰小W:这里给出两种方法😎

(一)、最简单的操作:我觉得这个方法最适合你,所以还是先介绍这个吧😂

①、新建一个属于自己文件夹

②、新建两个Python文件,文件名:mapper.py  reducer.py

③.将下面的代码复制到这个文件里面,按住:Ctrl+S 保存就好了!!!

对应的代码就在下面,点击旁边的复制按钮就可以复制了

(二)、稍微带一点点的技术操作,脱离鼠标的控制,速度贼快

进入你的文件目录:cd ljw

使用vi命令自动创建文件,然后编辑写入内容,一步到位

vi mapper.py

至于reduce.py 也是这样操作

👸小L:好,明白了

mapper.py


  
  1. #!/usr/bin/env python
  2. import sys
  3. # input comes from STDIN (standard input)
  4. for line in sys.stdin:
  5. # remove leading and trailing whitespace
  6. line = line.strip()
  7. # split the line into words
  8. words = line.split()
  9. # increase counters
  10. for word in words:
  11. # write the results to STDOUT (standard output);
  12. # what we output here will be the input for the
  13. # Reduce step, i.e. the input for reducer.py
  14. #
  15. # tab-delimited; the trivial word count is 1
  16. print '%s\t%s' % (word, 1)

reducer.py


  
  1. #!/usr/bin/env python
  2. from operator import itemgetter
  3. import sys
  4. current_word = None
  5. current_count = 0
  6. word = None
  7. # input comes from STDIN
  8. for line in sys.stdin:
  9. line = line.strip()
  10. word, count = line.split( '\t', 1)
  11. try:
  12. count = int(count)
  13. except ValueError:
  14. continue
  15. if current_word == word:
  16. current_count += count
  17. else:
  18. if current_word:
  19. # write result to STDOUT
  20. print '%s\t%s' % (current_word, current_count)
  21. current_count = count
  22. current_word = word
  23. # do not forget to output the last word if needed!
  24. if current_word == word:
  25. print '%s\t%s' % (current_word, current_count)

有小伙伴发现:Python代码竟然用的2版本的,本来是要用3的,但是这篇文章本来就是:合为时而作!!!要适合他们的才是最好的!

 

二、把大象装进冰箱

🐰小W:将刚刚的两个文件,放在虚拟机里面,路径如下:

首先要在这里新建一个mapreduce

/home/hadoop/ljw

🐰小W:测试脚本是否可以运行

切换到该路径下:

cd /home/hadoop/ljw

测试代码如下:

echo "foo foo quux labs foo bar quux" |./mapper.py | sort |./reducer.py


🐰小W:这里需要添加权限,为确保程序可以执行:这里的 +x 表示可以让它变成可执行的文件程序

👸小L:为什么呀?太多的疑问了

🐰小W:对于chmod +x file 来说就是将file改为可执行状态,在linux因高亮语法,会让file文件显示绿色。对于灰色的文件来说,没有可执行的权限,这是若我们给它chmod +x后它将会变为可执行的绿色文件。

👸小L:但是有的时候他们用的chmod 777 file 是什么意思呀?

🐰小W:其实吧,在操作文件的权限的时候可以使用数字,也可以使用- + = ,也可以使用数字:4 2 1,下面详细介绍一下,全面复习一下:


u User,即文件或目录的拥有者

g Group,即文件或目录的所属群组

o Other,除了文件或目录拥有者或所属群组之外,其他用户皆属于这个范围

a All,即全部的用户,包含拥有者,所属群组以及其他用户

mode : 权限设定字串,格式如下 : [ugoa…][[±=][rwxX]…][,…]

其中+ : 表示增加权限、- 表示取消权限、= 表示唯一设定权限。
r 读取权限,数字代号为“4”;w 写入权限,数字代号为“2”;x 执行或切换权限,数字代号为“1”;- 不具任何权限,数字代号为“0”;
s 特殊功能说明:变更文件或目录的权限
命令中各选项的含义为:

-c : 若该档案权限确实已经更改,才显示其更改动作
-f : 若该档案权限无法被更改也不要显示错误讯息
-v : 显示权限变更的详细资料
-R : 对目前目录下的所有档案与子目录进行相同的权限变更(即以递回的方式逐个变更)
--help : 显示辅助说明
--version : 显示版本
操作对象who可是下述字母中的任一个或者它们的组合:
u 表示“用户(user)”,即文件或目录的所有者。
g 表示“同组(group)用户”,即与文件属主有相同组ID的所有用户。
o 表示“其他(others)用户”。
 

绿色文件: 可执行文件,可执行的程序
红色文件:压缩文件或者包文件
蓝色文件:目录
白色文件:一般性文件,如文本文件,配置文件,源码文件等
浅蓝色文件:链接文件,主要是使用ln命令建立的文件
红色闪烁:表示链接的文件有问题
黄色:表示设备文件
灰色:表示其他文件

chmod 777的语法为:chmod abc file
其中a,b,c各为一个数字,分别表示User、Group、Other的权限。
r=4,w=2,x=1
若要rwx属性则4+2+1=7;
若要rw-属性则4+2=6;
若要r-x属性则4+1=5

案例:

chmod a=rwx file 和chmod 777 file效果相同
chmod ug=rwx,o=x file和chmod 771 file效果相同
若用chmod 4755 filename可使此程式具有root的权限

综上chmod +x 是将文件状态改为可执行,而chmod 777 是改变文件读写权限


👸小L:好像懂了,这得消化一下,哈哈哈,太多的知识点了


 🐰小W:接下里复制代码,改权限吧

chmod +x reducer.py
chmod +x mapper.py

测试脚本代码

 🐰小W:首先测试一下mapper.py这个文件,是否是我们所需要的执行效果

echo "foo foo quux labs foo bar quux" | ./mapper.py

这里首先使用Linux里面的命令 :echo 将文本打印,然后使用 | 管道符的命令 ./ 是表示执行文件

 

👸小L:又遇到知识盲区了.......

 🐰小W:echo 可以打印字符串,就像我们的Python:print('hello word!'),其次这个 | 叫做管道符,它所代表的就是前面一个语句的结果输出作为后面一条语句的输入,这个就是管道符,使用管道符有利于我们程序的结构化执行

 🐰小W:" ./ “ 的方式类似于新建了一个shell, 在这个新建的shell中去执行脚本中的程序,类似于新建了一个子进程,但这个子进程不继承父进程的所有非export类型的变量,并且脚本中对非export环境变量的创建或修改不会反馈到外部调用shell中,感觉说的有点太专业了,简单点就是执行这个程序

🐰小W:当然我觉得有必要补充一下,其他的相关知识


 

linux 中在shell中使用 " . " 和  " ./ " 执行的区别:

1. 如果使用" ./ " 执行,可以理解为程序运行在一个全新的shell中,不继承当前shell的环境变量的值, 同时若在程序中改变了当前shell中的环境变量(不使用export),则当前shell的环境变量值不变。

2. 如果使用” . "执行,则程序继承当前shell中的环境变量,同时,若在程序中改变了当前shell中的环境变量(不使用export),则当前shell中该环境变量的值也会改变

另外一个区别点在于, “ ./ "只能用于拥有执行权限的文件, 而 ” . " 则可以暂时提升


👸小L:原来如此啊,懂了懂了😉

🐰小W:这个是执行结果,看看你的执行结果是否一样

🐰小W:再去执行一下下面的代码,看看reduce.py是不是可以运行成功

echo "foo foo quux labs foo bar quux" |./mapper.py | sort |./reducer.py

👸小L:好像没有问题给🐮👍

 

测试结束,集群运行!

🐰小W:刚刚是为了测试这些脚本的准确性和正确性,下面就开始在hadoop的集群运行了,准备了一个文本文件(西游记读物)别名:book.txt

一切准备就绪,我们将在运行Python MapReduce job 在Hadoop集群上。像我上面所说的,我们使用的是HadoopStreaming 帮助我们传递数据在Map和Reduce间并通过STDIN和STDOUT,进行标准化输入输出。

👸小L:那怎么做呢?

🐰小W:首先将这个文件从复制到Ubuntu的文件夹

👸小L:好了,然后应该怎么做呢?😳

🐰小W:然后就看我的操作哈😀😀😀😀

最重要的第一步:start-all.sh,开启集群,不然在hdfs 操作的时候,会拒接连接!

1.使用命令:cat book.txt 查看文件内容

2.上传这个文件到hdfs分布式文件

首先在hdfs里面建一个存放数据的文件夹

hdfs dfs -mkdir ljw

上传

hdfs dfs -copyFromLocal book.txt ljw

查看

hdfs dfs -ls ljw

数据准备好了,然后就是编写一个执行文件了

👸小L:等等,我看老师发我的就是没执行文件,为什么要编写一个执行文件了?

🐰小W:你想一下如果真的在实际操作过程中,在终端修改代码那岂不是很麻烦,写一个独立的文件是比较好的选择。

1.首先新建一个文件:run.sh

2.配置参数

🐰小W:首先找到Hadoop的文件路径

sudo find / -name hadoop-stream*

🐰小W:run.sh 里面的内容如下,直接复制到里面即可!!!


  
  1. hadoop jar '/home/hadoop/hadoop-2.7.3/share/hadoop/tools/lib/hadoop-streaming-2.7.3.jar' \
  2. -mapper 'python mapper.py' \
  3. -file /home/hadoop/ljw/mapper.py \
  4. -reducer 'python reducer.py' \
  5. -file /home/hadoop/ljw/reducer.py \
  6. -input hdfs:/user/hadoop/ljw/book.txt \
  7. -output /ljw/result

👸小L:这个里面的一些代码具体是什么含义呀?

🐰小W:第一行是告诉 Hadoop 运行 Streaming 的 Java 程序,接下来的是参数:这里的mapper 后面跟的其实是一个命令。也就是说,-mapper 和 -reducer 后面跟的文件名不需要带上路径。而 -file 后的参数需要带上路径,为了让 Hadoop 将程序分发给其他机器,需要-file 参数指明要分发的程序放在哪里。

🐰小W:注意:如果你在 mapper 后的命令用了引号,加上路径名反而会报错说找不到这个程序。(因为 -file 选项会将对应的本地参数文件上传至 Hadoop Streaming 的工作路径下,所以再执行 -mapper 对应的参数命令能直接找到对应的文件。

🐰小W:-input 和 -output 后面跟的是 HDFS 上的路径名,这里的 input/book.txt 指的是input 文件夹下刚才上传的文本文件,注意 -output 后面跟着的需要是一个不存在于 HDFS 上的路径,在产生输出的时候 Hadoop 会帮你创建这个文件夹,如果已经存在的话就会产生冲突。因此每次执行 Hadoop Streaming 前可以通过脚本命令 hadoop fs -rmr 清除输出路径。

🐰小W:由于 mapper 和 reducer 参数跟的实际上是命令,所以如果每台机器上 python 的环境配置不一样的话,会用每台机器自己的配置去执行 python 程序。

👸小L:看来这个概念还要好好学习一下😉

🐰小W:对滴哟😛

下面来看看效果吧

👸小L:这是已经成功了吗?

🐰小W:对滴哈,下面看看结果

🐰小W: 查看命令

hdfs dfs -ls /ljw/result/

hdfs dfs -cat /ljw/result/part-00000

👸小L:终于出来了!!!!太棒啦😀

🐰小W:这里有几个需要特别强调的,感觉在这个问题上面花了很久时间😭

🐰小W:首先在配置执行文件:run.sh的时候,我们的路径一定不要写错了,其次我们的输入文件是hdfs里面的路径,但是我们最开始新建的时候直接使用mkdir ljw 其实自动创建在/usr/hadoop/路径下面的,具体问题可以看看这个文章:点击此处查看!

🐰小W:注意输出的文件是在hdfs里面的,是不需要创建的,如果创建了会起冲突的,所以只需要写一个文件就好了,会自动创建,比如ljw下面的result。

 

三、关闭冰箱

🐰小W:关闭冰箱就非常简单了,注意我们每次在自己的虚拟机启动集群之后需要关闭,使用命令:stop-all.sh

👸小L:好的,我记住了

🐰小W:这个使用Python实现Hadoop MapReduce程序,你应该会了吧,哈哈哈😉

👸小L:会了,感觉要好好看了

🐰小W:👍

👸小L:那我去看了哈

🐰小W:还没有完哟,下面有一系列的hdfs语法案例操作,也可以看看

 

hdfs语法合集

🐰小W:dfs基本命令总结

一、启动Hadoop:

🐰小W:start-all.sh

二,hdfs命令

1、统一格式:
🐰小W:hdfs dfs -命令 文件路径


2、查看目录下的文件或文件夹:
🐰小W:hdfs dfs -ls /


3、 将本地文件上传到hdfs上:

🐰小W:hdfs dfs -put 本地文件路径 远程路径

🐰小W:hdfs dfs -moveFromLocal 本地文件路径 远程路径

🐰小W:hdfs dfs -copyFromLocal 本地文件路径 远程路径

4、 在hdfs上创建文件
🐰小W:hdfs dfs -touchz 文件名 

5, 在hdfs上创建文件夹:

🐰小W:hdfs dfs -mkdir 文件夹名

6、从hdfs文件系统上下载文件到本地文件系统:
🐰小W:hdfs dfs -get 远程路径 本地路径 

7、 在hdfs文件系统中更改文件名与移动文件位置:
🐰小W:hdfs dfs -mv 远程路径1 远程路径2
🐰小W:hdfs dfs -mv 文件名1 文件名2 

8、在hdfs文件系统中复制文件:
🐰小W:hdfs dfs -cp 远程路径1 远程路径2 

9、 hdfs文件系统中删除文件或目录:
🐰小W:hdfs dfs -rm 文件名或目录名

10、查看hdfs文件系统中的文件:
🐰小W:hdfs dfs -cat 文件名

11、向hdfs文件系统中的文件追加信息:
🐰小W:hdfs dfs -appendToFile 文件1 文件2

解释:向文件2中写入信息:在本地系统先创建一个文件,写入信息,在使用该命令,将信息加入文件2。 

12、 将hdfs上的同名文件,进行合并,再下载到本地文件系统:
🐰小W:hdfs dfs -getmerge 远程路径 本地路径

🐰小W:这些是常见的hdsf命令操作!!!

👸小L:好多啊,感觉要记住很多给

🐰小W:其实都是有规律,记住使用hdfs的时候:开头一定是:hdfs dfs -  然后就是Linux里面的命令了,还有就是在使用hdfs的时候,一定要启动集群哟

👸小L:好😀

加餐案例😉

🐰小W:这里还有一些案例操作,你也可以看看😉

🐰小W:安全模式,查看当前的状态:hdfs dfsadmin -safemode get
🐰小W:进入安全模式:hdfs dfsadmin -safemode enter
🐰小W:强制离开安全模式:hdfs dfsadmin -safemode leave
🐰小W:一直等待直到安全模式结束:hdfs dfsadmin -safemode wait
🐰小W:在hdfs里面输入命令,与Linux里面类似。只是需要在命令行开头加-
🐰小W:查看该目录下的子文件,递归查询:hdfs dfs -ls -R /home
🐰小W:移动文件夹或者文件:hdfs dfs -mv 源文件的位置 目标位置(如果是目录文件夹需要在后面加入/ 如果是文件则不需要)
🐰小W:递归删除home目录下的子文件或者子目录:hdfs dfs -rm -r /home/文件
🐰小W:删除目录需要把参数改为d即可
🐰小W:创建多级文件夹需要加-P参数,如果父目录不存在,则创建父目录
🐰小W:新建文件:hdfs dfs -touchz /whw/whw.txt 然后我们可以利用:hdfs dfs ls -R /whw 查看
🐰小W:上传文件:首先要在本地上面创建一个文件,注意这个时候不需要再touch后加z,我们创建好之后,利用:hdfs dfs -put 本地文件位置 hdfs目标位置,也可以利用:hdfs dfs -copyFromLocal 本地文件位置 hdfs目标位置
🐰小W:移动文件:hdfs dfs -moveFromLocal 本地文件位置 hdfs目标位置
🐰小W:将hdfs上的文件下载到本地位置:hdfs dfs -get hdfs的位置 本地目标位置/重命名,也可以用hdfs dfs -copyToLocal hdfs的位置 本地目标位置
🐰小W:查看文件:hdfs dfs -cat 文件位置
🐰小W:追写文件:hdfs dfs -appendToFile 本地文件 hdfs文件(两者都是相同的文件类型)
🐰小W:hdfs里面的文件复制:hdfs dfs -cp 源文件 复制文件 参数:-f 如果目标文件存在则强制覆盖。-p保留文件的属性,移动文件(改名文件):hdfs dfs -mv 源文件 目标文件
🐰小W:hdfs中的目录下的文件(不包含子目录)合并后在下载到本地:hdfs dfs -getmerge 本地文件(位置默认,不需要添加)
😉😉😉😉😉😉😉😉😉😉😉😉😉

关于Hadoop里面的一些坑,你还知道哪些?欢迎留言评论区,帮助👸小L快乐的学习哟😀

每文一语

有一种快乐叫做和你一起😛😉


转载:https://blog.csdn.net/weixin_47723732/article/details/115902585
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场