安装Thrift

安装Thrift的具体操作,请点击链接

pip install thrift

安装happybase

pip install happybase

连接(happybase.Connection)

happybase.Connection(host=’localhost’, port=9090, timeout=None, autoconnect=True, table_prefix=None, table_prefix_separator=b’_’, compat=’0.98’, transport=’buffered’, protocol=’binary’)

获取连接实例

host:主机名
port:端口
timeout:超时时间
autoconnect:连接是否直接打开
table_prefix:用于构造表名的前缀
table_prefix_separator:用于table_prefix的分隔符
compat:兼容模式
transport:运输模式
protocol:协议

connection = happybase.Connection(host="192.168.0.156",port=9090,timeout=None,autoconnect=True,table_prefix=None,table_prefix_separator=b'_',compat='0.98', transport='buffered',protocol='binary')

使用连接池

Hbase自带有线程安全的连接池,踏允许多个线程共享和重用已经打开的连接。这对于多线程的应用是非常有用的。当一个线程申请一个连接,它将获得一个租赁凭证,在此期间,这个线程单独享有这个连接。当这个线程使用完该连接之后,它将该连接归还给连接池以便其他的线程可以使用

# 创建连接,通过参数size来设置连接池中连接的个数
pool = happybase.ConnectionPool(size=3, host='10.1.13.111', table_prefix='myProject')
# 获取连接
with pool.connection() as connection:
    print connection.tables()

open():打开传输,无返回值

connection.open()

close():关闭传输,无返回值

connection.close()
  • compact_table(name,major=False):压缩指定表格,无返回值

    • name:表名
    • major:是否主要压缩
connection.compact_table(name,major=False)
  • create_table(name,families):创建表,无返回值

    • name:表名
    • families:列族
families = {
    "cf":dict(),
    "df":dict()
}
connection.create_table(name,families)      # 如果连接时,有传递表前缀参数时,真实表名将会是:"{}_{}".format(table_prefix,name)
connection.create_table(
    'my_table',
    {
        'cf1': dict(max_versions=10),
        'cf2': dict(max_versions=1, block_cache_enabled=False),
        'cf3': dict(),  # use defaults
    }
)

此时,我们再通过connection.tables()查看可以使用的table,结果为['my_table']

创建的table即my_table包含3个列族:cf1、cf2、cf3

使用table的命名空间

因为一个Hbase会被多个项目共同使用,所以就会导致table的命名冲突,为了解决这个问题,可以在创建table的时候,手动加上项目的名字作为table名字的前缀,例如myproject_xyz。

但是这样做比较麻烦,happybase帮我们做好了工作,我们可以在与Hbase建立连接的时候,通过设置table_prefix参数来实现这个功能

connection = happybase.Connection('10.1.13.111', table_prefix='myproject')

此时connection.tables()只会返回包含在该命名空间里的tables,且返回的tables的名字会以简单的形式显示,即不包含前缀。

  • delete_table(name,disable=False):删除表,无返回值

    • name:表名
    • disable:是否先禁用表
 connection.delete_table(name,disable=False)
  • disable_table(name):禁用表,无返回值

    • name:表名
connection.disable_table(name)
  • enable_table(name):启用表,无返回值

    • name:表名
connection.enable_table(name)
  • is_table_enabled(name):表是否已经被启用,返回一个bool值

    • name:表名
connection.is_table_enabled(name)
  • connection.table(name,user_prefix=True):获取一个表对象,返回一个happybase.Table对象

    • name:表名
    • user_prefix:是否使用表前缀,默认为True
table = connection.table(name,user_prefix=True)     # table为happybase.table.Table类型
  • connection.tables():获取Hbase实例中的表名列表,返回一个list
table_name_list = connection.tables()

表(happybase.Table)

  • happybase.Table(name,connection):获取表实例

    • name:表名
    • connection:连接
table = happybase.Table(name,connection)
  • cells(row, column, versions=None, timestamp=None, include_timestamp=False):获取单元格数据,返回一个list

    • row:行
    • column:列
    • versions:获取的最大版本数量,默认None,即获取所有
    • timestamp:时间戳,默认None,即获取所有时间戳版本的数据。可指定一个时间戳,获取小于此时间戳版本的所有数据
    • include_timestamp:是否返回时间戳,默认False
content = table.cells('row1','cf:1',5,timestamp=1514861929124,include_timestamp=True)
print content   # [('1', 1514861925674L)]
  • counter_set(row,column,value=0):设置计数器列为特定值,此方法在指定列中存储一个64位有符号整数值。无返回值

    • row:行
    • column:列
    • value:默认值,默认为0
table.counter_set(row,column,value=0)
  • table.counter_get(row,column):获取计数器列的值,返回当前单元格的值

    • row:行
    • column:列
content = table.counter_get(row,column)
  • counter_dec(row,column,value=1):计数器列递减,返回递减后单元格的值

    • row:行
    • column:列
    • value:每次递减的值,默认为1
content = table.counter_dec(row,column,value=1)
  • counter_inc(row,column,value=1):计数器列递增,返回递增后单元格的值

    • row:行
    • column:列
    • value:每次递增的值,默认为1
content = table.counter_inc(row,column,value=1)
  • delete(row, columns=None, timestamp=None, wal=True):删除指定行数据,无返回值

    • row:行
    • columns:列,默认为None,即删除所有列,可传入一个list或tuple来指定删除列
    • timestamp:时间戳,默认为None,即删除所有,可传入一个时间戳来删除小于等于此时间戳的所有数据
    • wal:是否写入wal,默认为True
table.delete(row, columns=None, timestamp=None, wal=True)
  • families():获取所有列族信息,返回一个dict
info = table.families()
print info

{
    'cf': {
        'max_versions': 3,
        'bloom_filter_vector_size': 0,
        'name': 'cf: ',
        'bloom_filter_type': 'NONE',
        'bloom_filter_nb_hashes': 0,
        'time_to_live': 2147483647,
        'in_memory': False,
        'block_cache_enabled': False,
        'compression': 'NONE'
    },
    'cd': {
        'max_versions': 3,
        'bloom_filter_vector_size': 0,
        'name': 'cd: ',
        'bloom_filter_type': 'NONE',
        'bloom_filter_nb_hashes': 0,
        'time_to_live': 2147483647,
        'in_memory': False,
        'block_cache_enabled': False,
        'compression': 'NONE'
    }
}
  • put(row, data, timestamp=None, wal=True):插入数据,无返回值

    • row: 行
    • data: 数据,dict类型,{列:值}构成,列与值皆为str类型
    • timestamp:时间戳,默认None,即写入当前时间戳
    • wal:是否写入wal,默认为True
# 在row1行,cf:1列插入值1
table.put("})

使用put一次只能存储一行数据

如果row key已经存在,则变成了修改数据

更好的存储数据

table.put()方法会立即给Hbase Thrift server发送一条命令。其实这种方法的效率并不高,我们可以使用更高效的table.batch()方法。

# 使用batch一次插入多行数据
bat = table.batch()
bat.put('www.test5.com', {'cf1:price': 999, 'cf2:title': 'Hello Python', 'cf2:length': 34, 'cf3:code': 'A43'})
bat.put('www.test6.com', {'cf1:content': u'剃须刀', 'cf1:price': 168, 'cf1:rating': '97%'})
bat.put('www.test7.com', {'cf3:function': 'print'})
bat.send()

更有用的方法是使用上下文管理器来管理batch,这样就不用手动发送数据了,即不再需要bat.send()

# 使用with来管理batch
with table.batch() as bat:
    bat.put(', 'cf3:code': 'A43'})
    bat.put(', 'cf1:rating': '97%'})
    bat.put('www.test7.com', {'cf3:function': 'print'})

还可以删除数据

# 在batch中删除数据
with table.batch() as bat:
    bat.put(', 'cf3:code': 'A43'})
    bat.put(', 'cf1:rating': '97%'})
    bat.put('www.test7.com', {'cf3:function': 'print'})
    bat.delete('www.test1.com')

batch将数据保存在内存中,知道数据被send,第一种send数据的方法是显示地发送,即bat.send(),第二种send数据的方法是到达with上下文管理器的结尾自动发送。这样就存在一个问题,万一数据量很大,就会占用太多的内存。所以我们在使用table.batch()的时候要通过batch_size参数来设置batch的大小

# 通过batch_size参数来设置batch的大小
with table.batch(batch_size=10) as bat:
    for i in range(16):
        bat.put('www.test{}.com'.format(i), {'cf1:price': '{}'.format(i)})
  • regions():检索此表的区域服务器信息
info = table.regions()
print info

# [{'name': 'ddd_ch,,1514948783663.caccaafa3df04cd75737a9effb5615d4.', 'server_name': 'slave3', 'port': 16020, 'end_key': '', 'version': 1, 'start_key': '', 'id': 1514948783663L}]
  • row(row, columns=None, timestamp=None, include_timestamp=False):获取一行数据,返回一个dict

    • row:行
    • columns: 列,默认为None,即获取所有列,可传入一个list或tuple来指定获取列
    • timestamp:时间戳。默认为None,即返回最大的那个时间戳的数据。可传入一个时间戳来获取小于此时间戳的最大时间戳的版本数据
    • include_timestamp:是否返回时间戳数据,默认为False
info = table.row(row, columns=None, timestamp=None, include_timestamp=False)
检索多行数据
# 检索多行数据
rows = table.rows(['www.test1.com', 'www.test4.com'])
print rows

返回的是一个list,list的一个元素是一个tuple,tuple的第一个元素是row key,第二个元素是row key的值

如果想使检索多行数据即table.rows()返回的结果是一个字典,可以这样处理

# 检索多行数据,返回字典
rows_dict = dict(table.rows(['www.test1.com', 'www.test4.com']))
print rows_dict

如果想使table.rows()返回的结果是一个有序字典,即OrderedDict,可以这样处理

# 检索多行数据,返回有序字典
from collection import OrderedDict
rows_ordered_dict = OrderedDict(table.rows(['www.test1.com', 'www.test4.com']))
print rows_ordered_dict

更好地检索数据

# 通过指定列族来检索数据
row = table.row('www.test1.com', columns=['cf1'])
print row
# 通过指定列族中的列来检索数据
row = table.row('www.test1.com', columns=['cf1:price', 'cf1:rating'])
print row
print row['cf1:price']

在Hbase里,每一个cell都有一个时间戳timestamp,可以通过时间戳来检索数据

# 通过指定时间戳来检索数据,时间戳必须是整数
row = table.row('www.test1.com', timestamp=1489070666)
print row

默认情况下,返回的数据并不会包含时间戳,如果你想获取时间戳,这样就可以了

# 在返回的数据里面包含时间戳
row = table.row(row='www.test1.com', columns=['cf1:rating', 'cf1:price'], include_timestamp=True)
print row

对于同一个单元的值,Hbase存储了多个版本,在创建表的时候可以通过max_versions参数来设置一个列族的最大版本号,如果想检索某一cell所有的版本,可以这样

# 检索某一个cell所有的版本
cells = table.cells(b'www.test1.com', column='cf1:price')
print cells

也可以通过version参数来指定需要检索的前n个版本,如下

# 通过设置version参数来检索前n个版本
cells = table.cells(b'www.test1.com', column='cf1:price', versions=3)
print cells

删除数据

# 删除一整行数据
table.delete('www.test4.com')
# 删除一个列族的数据
table.delete('www.test2.com', columns=['cf1'])
# 删除一个列族中几个列的数据
table.delete('www.test2.com', columns=['cf1:name', 'cf1:price'])
  • scan(row_start=None, row_stop=None, row_prefix=None, columns=None, filter=None, timestamp=None, include_timestamp=False, batch_size=1000, scan_batching=None, limit=None, sorted_columns=False, reverse=False):获取一个扫描器,返回一个generator

row_start:起始行,默认None,即第一行,可传入行号指定从哪一行开始
row_stop:结束行,默认None,即最后一行,可传入行号指定到哪一行结束(不获取此行数据)
row_prefix:行号前缀,默认为None,即不指定前缀扫描,可传入前缀来扫描符合此前缀的行
columns:列,默认为None,即获取所有列,可传入一个list或tuple来指定获取列
filter:过滤字符串
timestamp:时间戳。默认为None,即返回最大的那个时间戳的数据。可传入一个时间戳来获取小于此时间戳的最大时间戳的版本数据
include_timestamp:是否返回时间戳数据,默认为False
batch_size:用于检索结果的批量大小
scan_batching:服务端扫描批处理
limit:数量
sorted_columns:是否返回排序的列(根据行名称排序)
reverse:是否执行反向扫描

scanner = table.scan(row_start=None, row_stop=None, row_prefix=None, columns=None, filter=None, timestamp=None, include_timestamp=False, batch_size=1000, scan_batching=None, limit=None, sorted_columns=False, reverse=False)

扫描一个table里的数据

# 全局扫描一个table
for key, value in table.scan():
    print key, value

结果如下:

 
 

这种全局扫描一个表格其实代价是很大的,尤其是当数据量很大的时候。我们可以通过设置开始的row key 或结束的row key或者同时设置开始和结束的row key来进行局部查询

# 通过row_start参数来设置开始扫描的row key
for key, value in table.scan(row_start='www.test2.com'):
    print key, value
# 通过row_stop参数来设置结束扫描的row key for key, value in table.scan(row_stop='www.test3.com'): print key, value
# 通过row_start和row_stop参数来设置开始和结束扫描的row key for key, value in table.scan(row_start='www.test2.com', row_stop='www.test3.com'): print key, value

另外,还可以通过设置row key的前缀来进行局部扫描

# 通过row_prefix参数来设置需要扫描的row key
for key, value in table.scan(row_prefix='www.test'):
    print key, value

常见问题

thriftpy.parser.exc.ThriftParserError: ThriftPy does not support generating module with path in protocol ‘e’\
解决:找到虚拟环境下的Lib\site-packages\thriftpy\parser\parser.py,line 488,进行如下操作:

if url_scheme == '':


修改为:
if len(url_scheme) <= 1:

happybase1.0 报错:ThriftPy does not support generating module with path in protocol 'f'

原因:happybase1.0在win下不支持绝对路径

具体原因:happybase要读取Python\Lib\site-packages\happybase\Hbase.thrift,但在Python\Lib\site-packages\thriftpy\parser\parser.py中的487行

url_scheme = urlparse(path).scheme
if url_scheme == '':

    with open(path) as fh:
        data = fh.read()
elif url_scheme in ('http', 'https'):('http', 'https'):
    data = urlopen(path).read()
else:
    raise ThriftParserError('ThriftPy does not support generating module '
                            'with path in protocol \'{}\''.format(
                                url_scheme))

path是Hbase.thrift的绝对路径(我的是“F:\SoftWare\Python27\Lib\site-packages\happybase\Hbase.thrift”),但经过urlparse(path).scheme后,url_scheme变成了“f”,(这也就是报错信息中最后的“f”)。根据代码,url_scheme既不为“”,也不包含(‘http’,'https'),则只能为raise报错。
解决方案:将488行的url_scheme == ''改为url_scheme in ('f', ''),即

url_scheme = urlparse(path).scheme
#if url_scheme == '':
if url_scheme in ('f', ''):
    with open(path) as fh:
        data = fh.read()
elif url_scheme in ('http', 'https'):
    data = urlopen(path).read()
else:
    raise ThriftParserError('ThriftPy does not support generating module '
                            'with path in protocol \'{}\''.format(
                                url_scheme))

注:'f'为盘符,就是我把python装在了f盘,只要能让那个判断为真就行。

相较于Hbase-Thrift,博主更建议使用HappyBase

Python操作HBase之happybase的更多相关文章

  1. python 操作 hbase

    python 是万能的,当然也可以通过api去操作big database 的hbase了,python是通过thrift去访问操作hbase 以下是在centos7 上安装操作,前提是hbase已经 ...

  2. 【Hbase三】Java,python操作Hbase

    Java,python操作Hbase 操作Hbase python操作Hbase 安装Thrift之前所需准备 安装Thrift 产生针对Python的Hbase的API 启动Thrift服务 执行p ...

  3. Hbase理论&&hbase shell&&python操作hbase&&python通过mapreduce操作hbase

    一.Hbase搭建: 二.理论知识介绍: 1Hbase介绍: Hbase是分布式.面向列的开源数据库(其实准确的说是面向列族).HDFS为Hbase提供可靠的底层数据存储服务,MapReduce为Hb ...

  4. python 操作Hbase 详解

    博文参考:https://www.cnblogs.com/tashanzhishi/p/10917956.html 如果你们学习过Python,可以用Python来对Hbase进行操作. happyb ...

  5. python操作Hbase

    本地操作 启动thrift服务:./bin/hbase-daemon.sh start thrift hbase模块产生: 下载thrfit源码包:thrift-0.8.0.tar.gz 解压安装 . ...

  6. 通过Python操作hbase api

    # coding=utf-8 # Author: ruin """ discrible: """ from thrift.transport ...

  7. 大数据自学5-Python操作Hbase

    在Hue环境中本身是可以直接操作Hbase数据库的,但是公司的环境不知道什么原因一直提示"Api Error:timed out",进度条一直在跑,却显示不出表. 但是在CDH后台 ...

  8. python连接hbase

    安装HBase HBase是一个构建在HDFS上的分布式列存储系统,主要用于海量结构化数据存储.这里,我们的目标只是为Python访问HBase提供一个基本的环境,故直接下载二进制包,采用单机安装.下 ...

  9. Python之操作HBASE数据库

    目前有两个库可以操作HBASE:hbase-thrift 和  happybase happybase使用起来比较简单方便,因此重点学习该库,hbase-thrift只做简要介绍. (一)hbase- ...

随机推荐

  1. C语言之实现随机数产生算法

    随机数,也就是在不同的时刻产生不同的数值.在UNIX操作系统和window的操作系统上,我们知道有一个函数rand,它就是用来产生随机数的函数API接口,那么它的原理如何实现? 如果约定a1=f(se ...

  2. 面试之路(13)-android apk之间共享数据的方式以及shareUserId详解

    1.通过content Provider/sharedPreferrence 2.通过shareUserId 我们详细介绍一下shareUserId: Android App Sandbox(andr ...

  3. Hyper Text Transfer Protocol(超文本传输协议)

    HTTP简介 HTTP协议是Hyper Text Transfer Protocol(超文本传输协议)的缩写,是用于从万维网(WWW:World Wide Web )服务器传输超文本到本地浏览器的传送 ...

  4. Java并发-容器

    同步容器类:同步容器类包括Vector和Hashtable.这些类实现线程安全的方式是:将它们的状态封装起来,并对每个公有方法进行同步,使得每次只有一个线程可以访问容器的状态.JDK1.2之后,提供了 ...

  5. java深入浅出之数据结构

    1.整形数据 byte.short.int.long,分别是1248个字节的存储量,取值范围也是依次增大的,其中int是正负21亿多: long a = 1111222233334444L:记住后面要 ...

  6. 快速开发框架,及库存管理系统,基于easyui框架和C#语言MVC、EntityFrameWork、T4模板技术。

    快速开发框架,及库存管理系统,基于easyui框架和C#语言MVC.EntityFrameWork.T4模板技术. 产品界面如下图所示: 源码结构: 开放全部源码,如有需要请联系,QQ:1107141 ...

  7. Vue作者尤雨溪:以匠人的态度不断打磨完善Vue (图灵访谈)

    访谈对象: 尤雨溪,Vue.js 创作者,Vue Technology创始人,致力于Vue的研究开发. 访谈内容: 你为何选择从事前端方面的工作? 其实,我本科读的是艺术史,研究生阶段学习Design ...

  8. 学习ASP.NET Core Razor 编程系列九——增加查询功能

    学习ASP.NET Core Razor 编程系列目录 学习ASP.NET Core Razor 编程系列一 学习ASP.NET Core Razor 编程系列二——添加一个实体 学习ASP.NET ...

  9. Selenium2Lib库之操作浏览器相关的关键字实战

    1.1  操作浏览器相关的关键字 Selenium2Lib提供了与浏览器交互的关键词 1.1.1 Open Browser关键字 按F5 查看Open Browser关键字的说明,如下图: Open ...

  10. 微信授权、获取用户openid-纯前端实现——jsonp跨域访问返回json数据会报错的纯前端解决办法

    近来,倒霉的后台跟我说让我拿个openid做微信支付使用,寻思很简单,开始干活. 首先引导用户打开如下链接,只需要将appid修改为自己的就可以,redirect_url写你的重定向url https ...