使用Python-3.6连接操作远程完全分布式集群中的HBase-2.1

本文详细介绍如何使用Python和Thrift连接远程HBase集群,包括搭建环境、安装配置、Python代码实现基本操作如建表、读写数据、扫描数据等。
部署运行你感兴趣的模型镜像

前提条件

  1. 已安装Python-3.6。
  2. 已经有搭建好的完全分布式集群,并已经成功启动Hadoop,Zookeeper和HBase。笔者当前搭建好的集群是Hadoop-3.0.3Zookeeper-3.4.13HBase-2.1.0
HostnameIP
master10.0.86.245
ceph110.0.86.246
ceph210.0.86.221
ceph310.0.86.253

一、下载Thrift安装包到远程集群的master结点中

Thrift-0.11.0链接:https://github.com/SparksFly8/Tools

Ubuntu安装Thrift依赖:

apt-get install automake bison flex g++ git libboost1.55 libevent-dev libssl-dev libtool make pkg-config

CentOS-7.5安装Thrift依赖:

yum install automake bison flex g++ git libboost1.55 libevent-dev libssl-dev libtool make pkg-config

解压并编译thrift,我是解压到/usr/local/中。

tar -zxvf thrift-0.11.0.tar.gz
cd thrift-0.11.0
./configure --with-cpp --with-boost --with-python --without-csharp --with-java --without-erlang --without-perl --with-php --without-php_extension --without-ruby --without-haskell  --without-go
make
make install

在master结点中Hbase安装目录下的/usr/local/hbase/bin目录启动thrift服务

[root@master bin]# ./hbase-daemon.sh start thrift

启动成功master状态如下:

在这里插入图片描述

二、本地Python连接远程集群中的HBase

我已将下面提到的所有方法分别整理成函数,并加入自己的需求在数据获取方面进行改善,欲看完整代码请见我的GitHub.

①分别下载两个安装包:thrifthbase-thrift
②在..\site-packages\hbase下替换两个文件,Hbase.pyttypes.py

F:\Env\virtual3.6\Lib\site-packages\hbase  # 我自己本地放置包的路径

③运行如下示例代码:连接HBase:

from thrift.transport import TSocket,TTransport
from thrift.protocol import TBinaryProtocol
from hbase import Hbase

# thrift默认端口是9090
socket = TSocket.TSocket('10.0.86.245',9090) # 10.0.86.245是master结点ip
socket.setTimeout(5000)

transport = TTransport.TBufferedTransport(socket)
protocol = TBinaryProtocol.TBinaryProtocol(transport)

client = Hbase.Client(protocol)
socket.open()

print(client.getTableNames())  # 获取当前所有的表名

在这里插入图片描述
运行结果对比HBase中数据表正确:
在这里插入图片描述

三、本地Python操作远程HBase常用方法

说明:以下案例均建立在上述成功连接HBase的基础上运行。

1.建表

【函数】:createTable(tableName, columnFamilies)
【参数】:tableName-表名; columnFamilies-列簇(列表)
【案例】:

from hbase.ttypes import ColumnDescriptor
# 定义列族
col1 = ColumnDescriptor(name='c1')
col2 = ColumnDescriptor(name='c2')
# 创建表
client.createTable('table',[col1, col2])
print(client.getTableNames())  # 获取当前所有的表名,返回一个包含所有表名的列表

等价于HBase Shell命令:

$ create 'table','c1','c2'

执行结果:

['table']

2.删除整表或删除某行数据

①删除整表
【函数】:deleteTable(tableName)
【参数】:tableName-表名
【案例】:

client.disableTable('table') # 删除表前需要先设置该表不可用
client.deleteTable('table')
print(client.getTableNames())  # 获取当前所有的表名,返回一个包含所有表名的列表

等价于HBase Shell命令:

$ disable 'table'
$ drop 'table'

执行结果:

[]

②删除指定表的某行数据
【函数】:deleteAllRow(tableName, row)
【参数】:tableName-表名;row-行键
【案例】:

client.deleteAllRow('table', '0001') # 删除第0001行所有数据

3.向某行某列插入/更新数据

【函数】:mutateRow(tableName, row, mutations)
【参数】:tableName-表名;row-行键;mutations-变化(列表);
【案例】:

def insertRow(client, tableName, rowName, colFamily, columnName, value):
    mutations = [Mutation(column='{0}:{1}'.format(colFamily, columnName), value=str(value))]
    client.mutateRow(tableName, rowName, mutations)
    print('在{0}表{1}列簇{2}列插入{3}数据成功.'.format(tableName, colFamily, columnName, value))

insertRow(client, 'table', '0001', 'c1', 'hobby2', 'watch movies')
print(client.get('table','0001','c1')[0].value) 

等价于HBase Shell命令:

$ put 'table','0001','c1:hobby2','watch movies'

执行结果:

在table表c1列簇hobby2列插入watch movies数据成功.

4.读取指定列簇指定列数据

【函数1】:get(tableName, row, column)
【函数2】:getVer(tableName, row, column, numVersions)

【参数】:tableName-表名;row-行键;numVersions-版本号;
column-指定列簇的列名(或仅填列簇名也ok);
【案例】:

# 若该行下指定列簇有多个列,则返回的是个包含多个列值的列表,可用索引来指明是哪一列
print(client.get('table','0001','c1')[index].value)
print(client.getVer('table','0001','c1',1))[index].value) 
# 获取固定列簇固定列的值,即仅包含一个值的列表,需用索引0来获取。
print(client.get('table','0001','c1:hobby2')[0].value)
print(client.getVer('table','0001','c1:hobby2',1))[0].value) 

等价于HBase Shell命令:

$ get 'table','0001','c1'
$ get 'table','0001','c1:hobby2'

执行结果:

watch movies

5.遍历指定行所有数据

【函数1】:getRow(tableName, row)
【函数2】:getRowWithColumns(tableName, row, columns)

【参数】:tableName-表名;row-行键;column-一个指定列簇指定列名的列表(若仅填列簇名就返回该列簇下所有列值);
【案例】:

results = client.getRow('table','0001')
for result in results:
    print(result.columns.get('c1:hobby2').value)
    
results = client.getRowWithColumns('table','0001',['c1'])) 
for result in results:
    print(result.columns.get('c1:hobby2').value)
    
results = client.getRowWithColumns('table','0001',['c1:hobby2'])
for result in results:
    print(result.columns.get('c1:hobby2').value)

等价于HBase Shell命令:

$ get 'table','0001'
$ get 'table','0001','c1'
$ get 'table','0001','c1:hobby2'

执行结果:

watch movies

【额外补充】:以下是我根据getRowgetRowWithColumns两个函数,经过数据清洗成常用字典形式,并过滤冒号,返回仅含有列名对应列值的字典。其中对于以下三种情况分别进行了处理:
①获取HBase指定表指定行的所有数据,以字典形式作为返回值。
②获取HBase指定表指定行指定列簇的所有数据,以字典形式作为返回值。
③获取HBase指定表指定行指定列簇指定列的数据,以字符串形式作为返回值。

'''
    功能:获取HBase指定表的某一行数据。
    :param client 连接HBase的客户端实例
    :param tableName 表名
    :param rowName 行键名
    :param colFamily 列簇名
    :param columns 一个包含指定列名的列表
    :return RowDict 一个包含列名和列值的字典(若直接返回指定列值,则返回的是字符串)
'''
def getRow(client, tableName, rowName, colFamily=None, columns=None):
    # 1.如果列簇和列名两个都为空,则直接取出当前行所有值,并转换成字典形式作为返回值
    if colFamily is None and columns is None:
        results = client.getRow(tableName, rowName)
        RowDict = {}
        for result in results:
            for key, TCell_value in result.columns.items():
                # 由于key值是'列簇:列名'形式,所以需要通过split函数以':'把列名分割出来
                each_col = key.split(':')[1]
                RowDict[each_col] = TCell_value.value # 取出TCell元组中的value值
        return RowDict
    # 2.如果仅是列名为空,则直接取出当前列簇所有值,并转换成字典形式作为返回值
    elif columns is None:
        results = client.getRowWithColumns(tableName, rowName, [colFamily])
        RowDict = {}
        for result in results:
            for key, TCell_value in result.columns.items():
                # 由于key值是'列簇:列名'形式,所以需要通过split函数以':'把列名分割出来
                each_col = key.split(':')[1]
                RowDict[each_col] = TCell_value.value  # 取出TCell元组中的value值
        return RowDict
    # 3.如果列簇和列名都不为空,则直接取出当前列的值
    elif colFamily is not None and columns is not None:
        results = client.getRow(tableName, rowName)
        for result in results:
            value = result.columns.get('{0}:{1}'.format(colFamily, columns)).value
        return value
    else:
        raise Exception('关键参数缺失,请重新检查参数!')

print(getRow(client, 'table', '0001'))
print(getRow(client, 'table', '0001', 'c1'))
print(getRow(client, 'table', '0001', 'c1', 'hobby2'))

执行结果:

# 第一个结果
{'age': '25', 'hobby1': 'reading', 'hobby2': 'watch movies', 'name': 'Tom', 'age': '30', 'hobby11': 'reading books'}
# 第二个结果
{'age': '25', 'hobby1': 'reading', 'hobby2': 'watch movies', 'name': 'Tom'}
# 第三个结果
watch movies

6.扫描并获取多行数据

【函数1】:scannerOpen(tableName, startRow, columns)
【功能】:从startRow行扫描到该表最后一行。
【函数2】:scannerOpenWithStop(tableName, startRow, stopRow, columns)
【功能】:从startRow行扫描到该表stopRow的前一行。
【参数】:tableName-表名;startRow-起始行键;stopRow-截止行键;column-一个指定列簇指定列名的列表(若仅填列簇名就返回该列簇下所有列值);
【案例】:

# 从20180900行扫描到最后一行
scannerId = client.scannerOpen('2018AAAI_Papers', '20180900', ['paper_info:title','paper_info:keywords'])
# 根据scannerId和rowsCnt(扫描的行数,可自己定义,若超出表的范围则扫描到表的最后一行)得到结果
results = client.scannerGetList(scannerId, rowsCnt)
# 从20180900行扫描到20180904行
scannerId = client.scannerOpenWithStop('2018AAAI_Papers', '20180900', '20180904', ['paper_info:title','paper_info:keywords'])
# 根据scannerId和rowsCnt(扫描的行数,可自己定义,若超出表的范围则扫描到表的最后一行)得到结果
results = client.scannerGetList(scannerId, rowsCnt)

【额外补充】:以下是我根据scannerOpenscannerOpenWithStop两个函数,经过数据清洗成常用字典形式,并过滤冒号,返回一个包含每行行键对应该行列值信息字典的字典。若传入行键或列名有误,则返回空列表。最终整合成scannerGetSelect方法。

def scannerGetSelect(client, tableName, columns, startRow, stopRow=None, rowsCnt=2000):
    '''
    依次扫描HBase指定表的每行数据(根据起始行,扫描到表的最后一行或指定行的前一行)
    :param client: 连接HBase的客户端实例
    :param tableName: 表名
    :param columns: 一个包含(一个或多个列簇下对应列名的)列表
    :param startRow: 起始扫描行
    :param stopRow:  停止扫描行(默认为空)
    :param rowsCnt:  需要扫描的行数
    :return MutilRowsDict: 返回一个包含多行数据的字典,以每行行键定位是哪一行
    '''
    # 如果stopRow为空,则使用scannerOpen方法扫描到表最后一行
    if stopRow is None:
        scannerId = client.scannerOpen(tableName, startRow, columns)
    # 如果stopRow不为空,则使用scannerOpenWithStop方法扫描到表的stopRow行
    else:
        scannerId = client.scannerOpenWithStop(tableName, startRow, stopRow, columns)
    results = client.scannerGetList(scannerId, rowsCnt)
    # 如果查询结果不为空,则传入行键值或列值参数正确
    if results:
        MutilRowsDict = {}
        for result in results:
            RowDict = {}
            for key, TCell_value in result.columns.items():
                # 获取该行行键
                rowKey = result.row
                # 由于key值是'列簇:列名'形式,所以需要通过split函数以':'把列名分割出来
                each_col = key.split(':')[1]
                RowDict[each_col] = TCell_value.value  # 取出TCell元组中的value值
                # 把当前含有多个列值信息的行的字典和改行行键存储在MutilRowsDict中
                MutilRowsDict[rowKey] = RowDict
        return MutilRowsDict
    # 如果查询结果为空,则传入行键值或列值参数错误,返回空列表
    else:
        return []

执行结果如下图:
在这里插入图片描述

四、完整Python操作远程HBase代码

# -*- coding: utf-8 -*-
__author__ = 'shiliang'
__date__ = '2019/3/1 23:48'

import math

from thrift.transport import TSocket,TTransport
from thrift.protocol import TBinaryProtocol
from hbase.ttypes import ColumnDescriptor
from hbase import Hbase
from hbase.ttypes import Mutation


def connectHBase():
    '''
    连接远程HBase
    :return: 连接HBase的客户端实例
    '''
    # thrift默认端口是9090
    socket = TSocket.TSocket('10.0.86.245',9090) # 10.0.86.245是master结点ip
    socket.setTimeout(5000)
    transport = TTransport.TBufferedTransport(socket)
    protocol = TBinaryProtocol.TBinaryProtocol(transport)
    client = Hbase.Client(protocol)
    socket.open()
    return client


def ListTables(client):
    '''
    列出所有表
    '''
    print(client.getTableNames())


def createTable(client, tableName, *colFamilys):
    '''
    创建新表
    :param client: 连接HBase的客户端实例
    :param tableName: 表名
    :param *colFamilys: 任意个数的列簇名
    '''
    colFamilyList = []
    # 根据可变参数定义列族
    for colFamily in colFamilys:
        col = ColumnDescriptor(name=str(colFamily))
        colFamilyList.append(col)
    # 创建表
    client.createTable(tableName,colFamilyList)
    print('建表成功!')


def deleteTable(client, tableName):
    '''
    删除表
    '''
    if client.isTableEnabled(tableName):
        client.disableTable(tableName)  # 删除表前需要先设置该表不可用
    client.deleteTable(tableName)
    print('删除表{}成功!'.format(tableName))

def deleteAllRow(client, tableName, rowKey):
    '''
    删除指定表某一行数据
    :param client: 连接HBase的客户端实例
    :param tableName: 表名
    :param rowKey: 行键
    '''
    if getRow(client, tableName, rowKey):
        client.deleteAllRow(tableName, rowKey)
        print('删除{0}表{1}行成功!'.format(tableName, rowKey))
    else:
        print('错误提示:未找到{0}表{1}行数据!'.format(tableName, rowKey))

def insertRow(client, tableName, rowName, colFamily, columnName, value):
    '''
    在指定表指定行指定列簇插入/更新列值
    '''
    mutations = [Mutation(column='{0}:{1}'.format(colFamily, columnName), value=str(value))]
    client.mutateRow(tableName, rowName, mutations)
    print('在{0}表{1}列簇{2}列插入{3}数据成功.'.format(tableName, colFamily, columnName, value))


def getRow(client, tableName, rowName, colFamily=None, columns=None):
    '''
    功能:获取HBase指定表的某一行数据。
    :param client 连接HBase的客户端实例
    :param tableName 表名
    :param rowName 行键名
    :param colFamily 列簇名
    :param columns 一个包含指定列名的列表
    :return RowDict 一个包含列名和列值的字典(若直接返回指定列值,则返回的是字符串)
    '''
    # 1.如果列簇和列名两个都为空,则直接取出当前行所有值,并转换成字典形式作为返回值
    RowDict = {}
    if colFamily is None and columns is None:
        results = client.getRow(tableName, rowName)
        for result in results:
            for key, TCell_value in result.columns.items():
                # 由于key值是'列簇:列名'形式,所以需要通过split函数以':'把列名分割出来
                each_col = key.split(':')[1]
                RowDict[each_col] = TCell_value.value # 取出TCell元组中的value值
        return RowDict
    # 2.如果仅是列名为空,则直接取出当前列簇所有值,并转换成字典形式作为返回值
    elif columns is None:
        results = client.getRowWithColumns(tableName, rowName, [colFamily])
        for result in results:
            for key, TCell_value in result.columns.items():
                # 由于key值是'列簇:列名'形式,所以需要通过split函数以':'把列名分割出来
                each_col = key.split(':')[1]
                RowDict[each_col] = TCell_value.value  # 取出TCell元组中的value值
        return RowDict
    # 3.如果列簇和列名都不为空,则直接取出当前列的值
    elif colFamily is not None and columns is not None:
        results = client.getRow(tableName, rowName)
        for result in results:
            value = result.columns.get('{0}:{1}'.format(colFamily, columns)).value
        return value
    else:
        raise Exception('关键参数缺失,请重新检查参数!')

def scannerGetSelect(client, tableName, columns, startRow, stopRow=None, rowsCnt=2000):
    '''
    依次扫描HBase指定表的每行数据(根据起始行,扫描到表的最后一行或指定行的前一行)
    :param client: 连接HBase的客户端实例
    :param tableName: 表名
    :param columns: 一个包含(一个或多个列簇下对应列名的)列表
    :param startRow: 起始扫描行
    :param stopRow:  停止扫描行(默认为空)
    :param rowsCnt:  需要扫描的行数
    :return MutilRowsDict: 返回一个包含多行数据的字典,以每行行键定位是哪一行
    '''
    # 如果stopRow为空,则使用scannerOpen方法扫描到表最后一行
    if stopRow is None:
        scannerId = client.scannerOpen(tableName, startRow, columns)
    # 如果stopRow不为空,则使用scannerOpenWithStop方法扫描到表的stopRow行
    else:
        scannerId = client.scannerOpenWithStop(tableName, startRow, stopRow, columns)
    results = client.scannerGetList(scannerId, rowsCnt)
    # 如果查询结果不为空,则传入行键值或列值参数正确
    if results:
        MutilRowsDict = {}
        for result in results:
            RowDict = {}
            for key, TCell_value in result.columns.items():
                # 获取该行行键
                rowKey = result.row
                # 由于key值是'列簇:列名'形式,所以需要通过split函数以':'把列名分割出来
                each_col = key.split(':')[1]
                RowDict[each_col] = TCell_value.value  # 取出TCell元组中的value值
                # 把当前含有多个列值信息的行的字典和改行行键存储在MutilRowsDict中
                MutilRowsDict[rowKey] = RowDict
        return MutilRowsDict
    # 如果查询结果为空,则传入行键值或列值参数错误,返回空列表
    else:
        return []


def bigInt2str(bigNum):
    '''
    大整数转换为字符串
    :param bigNum: 大整数
    :return string: 转换后的字符串
    '''
    string = ''
    for i in range(len(str(bigNum)),0,-1):
        a = int(math.pow(10, (i-1)))
        b = bigNum//a%10
        string += str(b)
    return string

if __name__ == '__main__':
    # 连接HBase数据库,返回客户端实例
    client = connectHBase()
    # 创建表
    # createTable(client, 'firstTable', 'c1', 'c2', 'c3')
    # 插入或更新列值
    # insertRow(client, 'firstTable', '0001', 'c1', 'name', 'sparks')
    # 获取HBase指定表的某一行数据
    # dataDict = getRow(client, 'firstTable', '0001')
    # print(dataDict)
    # 删除指定表某行数据
    # deleteAllRow(client, '2018AAAI_Papers', '20181106')
    # 依次扫描HBase指定表的每行数据(根据起始行,扫描到表的最后一行或指定行的前一行)
    MutilRowsDict = scannerGetSelect(client, '2018AAAI_Papers', ['paper_info:title','paper_info:keywords'], '20180900', '20180904')
    print(MutilRowsDict)
    # 列出所有表名
    ListTables(client)

【参考文献】:
[1] 使用 Python 和 Thrift 连接 HBase.
[2] 用Python3.6操作HBase之HBase-Thrift.

您可能感兴趣的与本文相关的镜像

Python3.9

Python3.9

Conda
Python

Python 是一种高级、解释型、通用的编程语言,以其简洁易读的语法而闻名,适用于广泛的应用,包括Web开发、数据分析、人工智能和自动化脚本

<think> 我们被要求回答关于Python连接操作HBase 2.1的方法。根据引用,我们需要参考站内引用,但注意引用中提到的版本可能不是2.1。不过,我们可以总结出一般步骤,并尝试适配到HBase 2.1。 引用中提到了使用Thrift连接,并且有两个版本(thriftthrift2)。在引用[4]中提到:“HBase有两个thrift版本的接口,称为thriftthrift2thrift1很可能被抛弃。” 因此,我们应该使用thrift2。 步骤大致如下: 1. 安装和配置HBase(单机或集群),并启动HBase2. 启动HBaseThrift2服务(注意引用[5]中启动的是thrift,我们需要启动thrift2)。 3. 生成PythonThrift客户端代码(使用HBase.thrift文件,但注意版本对应)。 4. 安装ThriftPythonThrift库。 5. 使用生成的客户端代码连接HBase。 但是,用户特别提到HBase 2.1,所以我们需要使用对应版本的HBase.thrift文件。 具体步骤: 1. 确保HBase 2.1已经安装并运行。可以参考引用[2]中的步骤,但注意下载HBase 2.1版本的二进制包。 2. 启动Thrift2服务: 在HBase的bin目录下,执行: ``` ./hbase-daemon.sh start thrift2 ``` 注意:引用[5]中启动的是thrift(即thrift1),这里我们启动thrift23. 下载HBase 2.1的源码,从中获取HBase.thrift文件(或者直接下载对应版本的thrift文件)。通常,在HBase源码的`hbase-thrift/src/main/resources/org/apache/hadoop/hbase/thrift`目录下可以找到thrift2的接口定义文件(如hbase.thrifthbase2.thrift)。注意,thrift2的接口定义文件可能是`hbase.thrift`,但为了确保,最好查找对应版本。 或者,我们可以从HBase的官方仓库获取:https://github.com/apache/hbase/tree/master/hbase-thrift/src/main/resources/org/apache/hadoop/hbase/thrift2.1版本中,thrift2的接口定义文件是`hbase.thrift`(在thrift2目录下)。但是请注意,在HBase 2.0之后,thrift2的接口定义文件通常位于`hbase-thrift/src/main/resources/org/apache/hadoop/hbase/thrift2`目录下,文件名为`hbase.thrift`。 所以,对于HBase 2.1,我们可以从这个链接获取:https://raw.githubusercontent.com/apache/hbase/branch-2.1/hbase-thrift/src/main/resources/org/apache/hadoop/hbase/thrift2/hbase.thrift 4. 使用Thrift生成Python客户端代码: 安装Thrift(参考引用[1]的安装步骤,但注意版本,0.10.0可能较旧,建议使用较新版本,至少0.13.0以上,因为HBase 2.1需要较新的Thrift支持)。 ``` thrift --gen py hbase.thrift ``` 这将生成一个`gen-py`目录,里面包含Python模块(如`hbase`)。 5. 将生成的`hbase`模块(在`gen-py`目录下)复制到Python的site-packages目录,或者将其放在你的项目目录中。 6. 安装PythonThrift库: ``` pip install thrift ``` 7. 编写Python客户端代码连接HBase。注意,Thrift2的接口与Thrift1不同,类名可能为`THBaseService`。 示例代码: ```python from thrift.transport import TSocket from thrift.transport import TTransport from thrift.protocol import TBinaryProtocol from hbase import THBaseService # 连接Thrift2服务 transport = TSocket.TSocket(&#39;localhost&#39;, 9090) # 默认端口9090 transport = TTransport.TBufferedTransport(transport) protocol = TBinaryProtocol.TBinaryProtocol(transport) client = THBaseService.Client(protocol) transport.open() # 使用client进行操作,例如获取表名 # 注意:THBaseService的API与Thrift1不同 # 例如,获取表名的方法可能是getTableNames,但具体需要查看生成的hbase.thrift中定义的接口 try: # 示例:获取所有表名 tables = client.getTableNames() print(tables) finally: transport.close() ``` 注意:生成的代码中,接口定义可能有所不同,需要根据实际的thrift文件查看具体的方法。 另外,引用[3]提到对于Python3可能需要替换两个文件(Hbase.py和ttypes.py),这是因为生成的代码可能不兼容Python3。如果使用Python3,可能需要手动调整生成的代码(或者寻找已经适配Python3的版本)。也可以尝试使用其他库,如happybase(但happybase只支持thrift1,不支持thrift2)。 因此,对于HBase 2.1,官方推荐使用thrift2,但thrift2Python客户端在Python3中可能存在问题,需要自行调整。 替代方案:使用happybase连接thrift1(但HBase 2.1thrift1可能已经被废弃,不推荐)。或者,可以考虑使用HBase的REST API(Stargate)或其他客户端,如async-hbase(支持thrift2和asyncio)。 总结步骤: 1. 安装并启动HBase 2.12. 启动thrift2服务:`hbase-daemon.sh start thrift2` 3. 下载对应版本的hbase.thrift文件(thrift2接口定义)。 4. 使用thrift生成Python客户端代码(确保thrift版本与HBase兼容)。 5. 将生成的代码放入Python路径,并安装thrift库。 6. 编写客户端代码连接。 由于thrift2Python客户端在Python3中可能存在兼容性问题,如果遇到问题,可能需要手动修改生成的代码(如将`import TTransport`改为`from thrift.transport import TTransport`等)。 另外,也可以考虑使用第三方库,如`hbase-thrift2`(但需要确认是否支持HBase 2.1)。 注意:以上步骤基于引用和HBase 2.1的官方文档。由于环境差异,具体操作可能需要调整。 最后,生成相关问题。 </think>### Python连接操作HBase 2.1的方法 在Python连接HBase 2.1主要通过Thrift2接口实现,以下是详细步骤: #### 1. **环境准备** - 安装HBase 2.1([官方下载](https://hbase.apache.org/downloads.html)) - 安装Thrift(需≥0.13.0版本): ```bash wget https://archive.apache.org/dist/thrift/0.13.0/thrift-0.13.0.tar.gz tar zxvf thrift-0.13.0.tar.gz cd thrift-0.13.0 ./configure make sudo make install ``` #### 2. **生成Python客户端代码** 从HBase源码获取Thrift2接口文件: ```bash wget https://raw.githubusercontent.com/apache/hbase/release-2.1.0/hbase-thrift/src/main/resources/org/apache/hadoop/hbase/thrift2/hbase.thrift thrift --gen py hbase.thrift ``` 这会生成`gen-py/hbase`目录,包含`THBaseService.py`等关键文件。 #### 3. **启动Thrift2服务** 在HBase安装目录执行: ```bash ./bin/hbase-daemon.sh start thrift2 ``` #### 4. **Python连接示例** ```python from thrift.transport import TSocket, TTransport from thrift.protocol import TBinaryProtocol from hbase import THBaseService # 创建连接 transport = TSocket.TSocket(&#39;localhost&#39;, 9090) transport = TTransport.TBufferedTransport(transport) protocol = TBinaryProtocol.TBinaryProtocol(transport) client = THBaseService.Client(protocol) transport.open() # 写入数据 from hbase.ttypes import TPut, TColumnValue put = TPut( row=b&#39;row1&#39;, columnValues=[ TColumnValue(family=b&#39;cf&#39;, qualifier=b&#39;name&#39;, value=b&#39;Alice&#39;) ] ) client.put(&#39;test_table&#39;, put) # 读取数据 from hbase.ttypes import TGet get = TGet(row=b&#39;row1&#39;) result = client.get(&#39;test_table&#39;, get) print(result.columnValues[0].value) # 输出: b&#39;Alice&#39; transport.close() ``` #### 5. **关键注意事项** 1. **Python3兼容性** 需手动修改生成的`*.py`文件: - 替换`from thrift.Thrift import *`为显式导入 - 添加`b`前缀处理字节字符串(如`b&#39;cf&#39;`) - 参考[HBase Python3补丁](https://github.com/apache/hbase/pull/123) 2. **Thrift2接口特性**: - 支持HBase 2.x新功能(如协处理器) -Thrift1更完整的API支持 - 使用`TColumnValue`结构化数据模型 3. **依赖安装**: ```bash pip install thrift ``` #### 替代方案 - **HappyBase**(仅支持Thrift1): ```python import happybase conn = happybase.Connection(&#39;localhost&#39;) ``` - **REST API**(通过`requests`调用): ```python import requests r = requests.get("http://localhost:8080/version") ``` > **注意**:Thrift2默认端口为9090,需确保防火墙开放。生产环境建议使用连接池管理Thrift连接[^5]。 ---
评论 4
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

SL_World

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值