业务场景大概是这样,我需要在公司hadoop集群上对博文进行结巴分词。我的数据是存储在hive表格中的,数据量涉及到五百万用户三个月内发的所有博文。

首先对于数据来说,很简单,在hive表格中就是两列,一列代表的是uid,一列代表的是博文内容。举个例子如下:

uid     content
12345 今天天气真好啊
23456 中午的食物真不错啊
... ...

对于hive表格,我在使用hadoop的时候,方法一般使用的是hive+python的形式,也就是从hive中一行行的读取数据,每一行都经过python文件进行处理,然后将结果插入到另一个新的表格中去。

在这个过程中,我们在python文件中需要导入结巴分词(或者其他比较好的分词包),即 import jieba;但是在运行程序的时候发现程序报错,通过查询错误(查询的方法很笨拙,第一感觉就是包出了问题,只要程序中没有包的时候没有错误,加入结巴分词有了错误,就知道错在哪里了)也就是说在公司集群的python运行环境下并没有结巴分词。

因为使用的是公司的集群,我没有权限加载新的包,这就需要我找到别的办法。

通过谷歌,我知道的绝大多是的解决办法都是基于hadoop mapreduce的(简单来讲,就是通过一个mapper文件,一个reducer文件实现一个程序的执行)我在这里是实现了一个简单的python版本的mapreduce程序

正如我在开头提到的,我在这里使用的是hive+python的方式处理hive表格,正式的名称我们可以称它为hadoop streaming(从本质上来讲hadoop streaming 和mapreudce是一样的,只不过使用的方式不同)。也正是基于两者的本质是一样的,所以经过我的苦思冥想,终于灵光一现,从hadoop mapreduce中的解决办法中类比出了在hadoo streaming 中的解决办法。 简单讲一下,mapreduce中解决办法就是在最后的执行程序中加上一行

hadoop -file jieba.mod

从本质上来讲,这句话的作用就是把本地的文件传输到集群上面,让这个hadoop集群有能力使用这个文件。我为什么这么理解呢? 从上面那个简单的python版mapreduce中的程序中,我们知道最后的执行命令大概是这样的:

$HADOOP_CMD jar $STREAM_JAR_PATH \
-input $INPUT_FILE_PATH \
-output $OUTPUT_PATH \
-mapper "python mapper.py" \
-reducer "python reducer.py" \
-file ./mapper.py \
-file ./reducer.py

具体上面的命令是什么意思,在这里就不详细讲了,可以去我那边文章中学一下。我这边就从感觉上讲一下这个东西。我们在程序中是使用了mapper文件和mapper文件的。这个文件也是在本地上,如果我们想要在集群上使用这两个文件,就需要我们使用命令将这两个文件从本地上传到集群上。我们使用的命令就是hadoop -file.

类比的,我们就知道hadoop -file jieba.mod 的作用就是把结巴压缩包上传到集群上去。

这一点就是最关键的地方!

在hadoop streaming中(hive+python),我们在使用hive UDF(hive 自定义函数)的时候,一定会用到add file这个命令。比如

add file ./process.py

process.py就是python处理数据的文件。我们为什么使用到这个命令呢?就是因为这个处理文件是在本地的。如果想要在集群上使用这个命令,就需要把这个文件上传到集群上去,在streaming我们就是使用add file 这个命令来把文件上传到集群上去的。

这样,我们就把两者的联系在了一起,也就是说,如果我们想把结巴分词这个包上传到集群上去,在mapreduce中我们使用的是haddop -file,在streaming中我们就要使用的是add file.

逻辑理清了,接下来就非常清楚了,就是写代码的工作了。

当然具体的博文数据肯定是比这个更加复杂的,比如在博文中会有着表情内容等等。我们假设上面的这博文表格名称为 temp_zida_blog_content.

大致的思想就是这样,接下来上代码:

首先我们从官网下载结巴分词包,点这里.

下载的文件名字为:jieba-0.39.zip 可能版本不同,名字不同。解压之后,进入这个文件,找到一个文件夹名字为'jieba'(不带版本号)(在这里一定要注意我们一定要要进入到解压缩之后的文件中找到这个不带版本号的文件,这个才是我们要压缩的文件,如果我们直接使用从官网下载之后的压缩文件,是会出错误的),对这个不带版本号的文件夹进行压缩,并改成mod后缀名:

zip -r jieba.zip jieba
mv jieba.zip jieba.mod

为了在python中使用结巴分词,我们在python代码中引入的就是jieba.mod。需要注意的一点就是这个jieba.mod需要和python代码在同一个目录下,所以为了处理数据方便,最好是把处理数据需要的所有代码和相应配置文件全部放在一个文件夹中。

这样在python代码中,我们就可以这样引入结巴分词包:

zida.py

import sys,math,random
reload(sys)
sys.setdefaultencoding('utf-8')
sys.path.append('./') #这个步骤非常的重要,点名了导入文件的路径
import zipimport importer = zipimport.zipimporter('jieba.mod')
jieba = importer.load_module('jieba')
import jieba
import re ##下面的代码就是对每一行导进来的hive表格内容进行处理,然后返回相应的处理之后的数据

正如我之前所说的,只是python中引入这个包,是不够的,因为我们现在python文件中使用的包是从本地中导进去的,那么也就是说并不能适用在公司的hadoop的集群中,所以我们还需要在shell脚本中进行相应的处理(这一步也就是我这个业务场景和我在谷歌找到解决办法很不一样的地方,他们都是在执行mapreduce的那一步加入了本地相应的文件)

##在下面这个函数中,最重要的就是add file ./jieba.mod;,它代表的就是使用上本地的包文件。这一步其实很容易通过dd file ./zida.py这行代码来理解。因为首先我们的shell脚本是在集群上运行的,为了处理hive表格数据,我们使用本地的python脚本,为了让python脚本能够在集群上跑,我们使用了这行代码,类似于把python脚本抛到集群上。类比去想,如果我们想在python脚本中使用相应的包,那么只需要在这里把相应的包抛上去就好了,然后在python脚本中导入就好,因为已经被抛到集群中了,当然可以被引用。

function process_data(){
cat <<EOF
add file ./jieba.mod;
add file ./zida.py;
INSERT OVERWRITE TABLE temp_zida_uids_bowen_content
select transform(tmp.*) using 'python zida.py test'
AS uid,bowen
FROM(
select a.uid,b.extend,b.content from
(select distinct(uid) from temp_zida_uids_day)a
left outer join
(select uid,extend,content from ods_tblog_content where dt>=dt_ods_tblog_content_90days_ago and dt<=dt_ods_tblog_content)b
on a.uid=b.uid
)tmp
EOF
} hive -e "`process_data`"
echo "process_data"

其实可以引申一下,如果我们想在python脚本中使用或者说读进来本地的文件,比如说停用词,我们还需要在shell脚本中add这个停用词文件,然后才能从python脚本中读取。具体可以看我这里的讲解如何在处理hive表格的python代码中导入外部文件

公司的python运行环境比较老旧了,还是2的版本,不支持中文,搞得我代码正确的情况下,失败了好多次,浪费了大量时间,一定要记住在python脚本文件最上面写上:

#coding=utf-8

接下来我列取一些我参考的网页

这个网页是我主要参考的部分-给了我很多的思考-使用Hadoop的MapReduce和jieba分词统计西游记中的词频-这个网页中很厉害,它不只是导入了结巴分词,还导入了Jieba.analyse,同时进行了相应的改变,比我这个要复杂一些

How can I include a python package with Hadoop streaming job?

[How to use Cascading with Hadoop Streaming]-谷歌上其他的解决办法基本上都是基于这个网页的解答,给了我很多启发(http://eigenjoy.com/2009/11/18/how-to-use-cascading-with-hadoop-streaming/)-从这个网页学到了在下载完结巴分词之后,解压之后还需要进去,把没有带版本号的那个文件夹进行一个压缩.

如何在hadoop中使用外部的python程序文件的更多相关文章

  1. 深度分析如何在Hadoop中控制Map的数量

    深度分析如何在Hadoop中控制Map的数量 guibin.beijing@gmail.com 很多文档中描述,Mapper的数量在默认情况下不可直接控制干预,因为Mapper的数量由输入的大小和个数 ...

  2. 如何在Linux中使用Firejail运行应用程序

    有时您可能希望使用在不同环境中未经过良好测试的应用程序,但您必须使用它们.在这种情况下,关注系统的安全性是正常的.在Linux中可以做的一件事是在沙箱中使用应用程序. “沙盒”是在有限环境中运行应用程 ...

  3. python操作txt文件中数据教程[3]-python读取文件夹中所有txt文件并将数据转为csv文件

    python操作txt文件中数据教程[3]-python读取文件夹中所有txt文件并将数据转为csv文件 觉得有用的话,欢迎一起讨论相互学习~Follow Me 参考文献 python操作txt文件中 ...

  4. 在windows中:双击运行Python程序、后台运行Python程序

    在windows中:双击运行Python程序.后台运行Python程序 安装Python解释器的windows环境,如果双击运行*.py的文件,会闪退.怎样避免闪退呢? 我们用python的日志输出程 ...

  5. python如何通过windows命令行运行一个python程序文件?

    python如何通过windows命令行运行一个python程序文件? cmd 进入到py文件对应目录下或者直接在上面的文件地址栏输入cmd,敲入回车 定位到对应的目录下 输入python xxx.p ...

  6. 如何在Anaconda中实现多版本python共存

    anaconda中Python版本是3.5,因为爬虫原因,需要Python2.7版本,因此,希望能在anaconda中Python3和Python2共存. 1. 打开Anaconda Prompt,可 ...

  7. 深度分析如何在Hadoop中控制Map的数量(摘抄)

    很多文档中描述,Mapper的数量在默认情况下不可直接控制干预,因为Mapper的数量由输入的大小和个数决定.在默认情况下,最终input占据了多少block,就应该启动多少个Mapper.如果输入的 ...

  8. 如何在Linux中自动删除或清理/tmp文件夹内容?

    每个Linux系统都有一个名为的目录/tmp,该目录已挂载了单独的文件系统. 它具有称为tmpfs的特殊文件系统.这是一个虚拟文件系统,操作系统将在系统引导时自动挂载/tmp挂载点. 如果要根据应用程 ...

  9. 如何在KEIL中编写模块化的C程序

    在KEIL中的模块化程序写法在使用KEIL的时候,我们习惯上在一个.c的文件中把自己要写的东西按照自己思路的顺序进行顺序书写.这样是很普遍的写法,当程序比较短的时候比如几十行或者一百多行,是没有什么问 ...

随机推荐

  1. wx.grid

    wxPython控件学习之wx.grid.Grid (包括对GridCellEditor和GridCelRender的扩展,以支持更多的grid cell 样式, 以GridCellColorEdit ...

  2. 【Leetcode】【Easy】Symmetric Tree

    Given a binary tree, check whether it is a mirror of itself (ie, symmetric around its center). For e ...

  3. matlab解方程

    [x1,y1,x2,y2]=solve('x1^2 + y1^2=1','x2^2-8*x2 +y2^2 +15=0','x1*x2 + y1 * y2=1','x1 + x2 =a','x1','y ...

  4. May 21st 2017 Week 21st Sunday

    The smallest deed is better than the greatest intention. 最微小的行动胜过最伟大的打算. Several years ago, just aft ...

  5. 什么是微信小程序

    官方给的说法是: 微信小程序,简称小程序,是一种不需要下载安装即可使用的应用,它实现了应用“触手可及”的梦想,用户扫一扫或搜一下即可打开应用 总结发现有这么几点: 1.免安装(不需要单独安装,是依托微 ...

  6. PHP设计模式——桥接模式

    <?php /* * 桥接模式 * 使用发送器,将一个类对象传入另一个类作为属性,耦合M+N个类 * */ abstract class Info { protected $_send = NU ...

  7. 2018.11.9 Dubbo入门学习

    1.什么是Dubbo dubbo.io 代表是开源的 DUBBO是一个分布式服务框架,致力于提供高性能和透明化的RPC远程服务调用方案,是阿里巴巴SOA服务化治理方案的核心框架,每天为2,000+个服 ...

  8. 【翻译】苹果官网的命名规范之 Code Naming Basics-General Principles

    苹果官方原文链接:General Principles 代码命名基本原则:通用规范   代码含义清晰 尽可能将代码写的简洁并且明白是最好的,不过代码清晰度不应该因为过度的简洁而受到影响.例如: 代码 ...

  9. Python-利用flask模块创建web接口

    一.创建一个实现登录的接口 import flask from flask import request #获取参数 # import json #post请求传入json对象时,通过json获取参数 ...

  10. git上传过滤忽略文件

    有些时候我们不想把某些文件纳入版本控制中,比如数据库文件,临时文件,设计文件等 在主目录下建立".gitignore"文件,此文件有如下规则: 忽略文件中的空行或以井号(#)开始的 ...