Skip to main content

用于 HBase 的 libhbase C API 的 Python 包装器

项目描述

pychbase

这是使用libhbase C API的 MapRDB 和 HBase 的 Python C 包装器。

pychbase仿照 HappyBase API,但它不使用 thrift,非常适合 MapRDB。

pychbase在 Python 2.7 和 MapR 5.1 上进行了测试。

LD_LIBRARY_PATH

要编译和导入pychbase,您的LD_LIBRARY_PATH必须具有包含libjvm.so的目录,通常位于以下任一位置:

  • $JAVA_HOME/lib/amd64/服务器

  • $JAVA_HOME/jre/lib/amd64/服务器

如果您将它与 MapR 一起使用,您的LD_LIBRARY_PATH上还必须有/opt/mapr/lib

例如,

export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$JAVA_HOME/lib/amd64/server:/opt/mapr/lib

安装

在 MapR 环境中安装

通常,在 MapR 环境中唯一需要担心的环境变量是 $PYCHBASE_LIBJVM_DIR

export PYCHBASE_LIBJVM_DIR=/usr/lib/jvm/jre-1.7.0/lib/amd64/server
virtualenv pychbase
cd pychbase
source bin/activate
pip install pychbase

# Or build it from source
git clone https://github.com/mkmoisen/pychbase.git
cd pychbase
python setup.py install

在非 MapR 环境中安装

请参阅 Cloudera 安装说明的自述文件末尾。

运行测试

tests目录中的config.py文件有两个常量, ZOOKEEPERTABLE_NAME,如果您在不修改的情况下运行测试,这可能不起作用

创建一个tests/local_config.py文件,如下所示:

ZOOKEEPERS = 'localhost:7222'
TABLE_NAME = 'testpychbase'

要运行测试,请确保在测试目录中,否则您将面临导入问题:

cd tests
python tests.py

目前,如果没有遇到导入问题,nosetests将无法工作。

用法

我试图尽可能地模仿伟大的 HappyBase API。

确保设置 LD_LIBRARY_PATH 环境变量:

# MapR
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$JAVA_HOME/jre/lib/amd64/server:/opt/mapr/lib

# Non MapR
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/lib/jvm/jre-1.7.0/lib/amd64/server::/home/matthew/libhbase/target/libhbase-1.0-SNAPSHOT/lib/native
export HBASE_LIB_DIR=/home/matthew/libhbase/target/libhbase-1.0-SNAPSHOT/lib/
# I've only gotten it to work on CDH4. If you are on CDH5 you'll need to mess around with the classpath some more

进口:

from pychbase import Connection, Table, Batch

要创建连接:

# On MapR, you don't need to specify the CLDBS/zookeepers:
connection = Connection()

# On Non-MapR environments, you'll need to specify the zookeepers:
connection = Connection('zookeeper-one:2181",zookeeper-two:2181",zookeeper-three:2181"')

创建和删除表:

# Create a table named 'test_table' with a single column family named 'f' with no additional attributes
connection.create_table('test_table', {'f': {}})
connection.delete_table('test_table')

要获得要操作的表:

table = connection.table('test_table')

放置、删除和从表中获取:

# Put a row with the current timestamp
table.put('rowkey1', {'f:foo': 'bar', 'f:hai': 'bai'})
data = table.row('rowkey1')
assert data == {'f:foo': 'bar', 'f:hai': 'bai'}

# Get a row and only include a single column
data = table.row('rowkey1', columns=('f:foo',))
assert data == {'f:foo': 'bar'}

# Delete the row
table.delete('rowkey1')
data = table.row('rowkey1')
assert data == {}

# Put a row with a given timestamp
table.put('rowkey1', {'f:foo': 'bar'}, timestamp=1000)
table.put('rowkey1', {'f:foo': 'BAR'}, timestamp=10000)

# Get a row with a given timestamp and include its timestamp
data = table.row('rowkey1', timestamp=1000, include_timestamp=True)
assert data == {'f:foo': ('bar', 1000)}

扫描:

# Full table scan:
for row, data in table.scan():
    pass

# Scan with a start and stop:
for row, data in table.scan('foo', 'bar'):
    pass

# Scan with a row prefix:
for row, data in table.scan(row_prefix='baz'): # E.g., start='baz', stop='baz~'
    pass

# Scan with a filter: # Check out tests.py on how to use all of the filters
for row, data in table.scan(filter="SingleColumnValueFilter('f', 'foo', =, 'binary:foo')":
    pass

# Scan a table but return only row keys, no rows:
table.put('foo', {'f:foo': 'foo'}
table.put('foo1', {'f:foo': 'foo'}
table.put('foo2', {'f:foo': 'foo'}

rows = list(table.scan(only_rowkeys=True))
assert rows == ['foo', 'foo1', 'foo2']

要计算表中的行数:

# Full table count:
count = table.count()

# Count all rows with a start and stop
count = table.count('foo', 'bar')

# Count all rows whose row key starts with a row prefix:
count = table.count(row_prefix='baz') # E.g., start='baz', stop='baz~'

# Count all rows with a filter:
count = table.count(filter="SingleColumnValueFilter('f', 'foo', =, 'binary:foo')")

批量放置:

batch = table.batch()
datas = [
    ('foo', 'a', 'b'),
    ('foo1', 'a1', 'b1'),
    ('foo2', 'a2', 'b2'),
]

for data in datas:
    batch.put(data[0], {'f:foo': data[1], 'f:bar': data[2]})

errors = batch.send()

assert errors == 0

批量删除:

batch = table.batch()
rows = ['foo', 'foo1', 'foo2']
for row in rows:
    batch.delete(row)

errors = batch.send()

assert errors == 0

请注意,batch.send()返回发生的错误数(如果有)。客户可以忽略这一点或引发异常。

batch = table.batch()
batch.put('foo', {'f:foo', 'bar'})
batch.put('foo', 'invalid')

errors = batch.send()
assert errors == 1

另一个辅助方法是table.delete_prefix(row_prefix),它删除包含以前缀开头的所有行。

table.put('foo', {'f:foo', 'foo'}
table.put('foo1', {'f:foo', 'foo'}
table.put('foo2', {'f:foo', 'foo'}
table.put('foo3', {'f:foo', 'foo'}
table.put('bar', {'f:bar', 'bar'}

number_deleted = table.delete_prefix('foo')
assert number_deleted == 3

assert table.count() == 2

请注意,尝试批处理/放置未转义的空终止符将导致它们被剥离。尝试使用带有非转义空终止符的行键将引发 TypeException。在尝试批处理/放置数据之前,用户有责任转义空终止符。

table.put('foo', {'f:foo\0bar': 'baz\0bak'})
data = table.row('foo')
assert data == {'f:foo': 'baz'}

table.put('bar', {'f:foo\\0bar': 'baz\00bak'})
data = table.row('foo')
assert data == {'f:foo\\0bar': 'baz\00bak'}

HappyBase 兼容性

这个库的一个目标是保持与 HappyBase 中的 API 的兼容性。

查看__init__.py以了解我尚未实现的 HappyBase 的哪些功能。

将来,如果用户使用未实现的功能,我将强制向 stderr 打印警告。

非 MapR 安装和环境变量指南

我没有在 Cloudera 上大量测试pychbase由于libhbase的类路径问题,我无法让它在 CDH5 上运行,虽然我能够使用 CDH4 启动并运行它,但一些测试失败了。在我看来,libhbase在 MapR 之外并不完全兼容。

export PYCHBASE_IS_MAPR=FALSE
export PYCHBASE_LIBJVM_DIR=/usr/lib/jvm/jre-1.7.0/lib/amd64/server
export PYCHBASE_INCLUDE_DIR=/home/matthew/libhbase/target/libhbase-1.0-SNAPSHOT/include
export PYCHBASE_LIBRARY_DIR=/home/matthew/libhbase/target/libhbase-1.0-SNAPSHOT/lib/native
virtualenv pychbase
cd pychbase
source bin/activate
pip install pychbase

# Or build it from source
git clone https://github.com/mkmoisen/pychbase.git
cd pychbase
python setup.py install

请注意,必须设置以下环境变量才能正确安装pychbase

  • PYCHBASE_IS_MAPR

  • PYCHBASE_LIBJVM_DIR

  • PYCHBASE_INCLUDE_DIR

  • PYCHBASE_LIBRARY_DIR

PYCHBASE_IS_MAPR

这默认为TRUE。如果您使用 Cloudera/etc,请确保:

export PYCHBASE_IS_MAPR=FALSE

PYCHBASE_LIBJVM_DIR

这是存放libjvm.so文件的目录。通常它位于以下任一位置:

  • $JAVA_HOME/lib/amd64/服务器

  • $JAVA_HOME/jre/lib/amd64/服务器

如果未设置PYCHBASE_LIBJVM_DIR,安装程序将检查是否 已设置JAVA_HOME,然后尝试上述每个目录。如果未设置JAVA_HOME,它将尝试默认为 /usr/lib/jvm/jre-1.7.0/

例子:

export PYCHBASE_LIBJVM_DIR=/usr/lib/jvm/jre-1.7.0/lib/amd64/server

PYCHBASE_INCLUDE_DIR

这包含/hbase/hbase.h和其他libhbase C 头文件。

如果PYCHBASE_IS_MAPR为真,则默认为/opt/mapr/include

对于非 MapR 环境,必须设置此项,否则安装将失败。

Cloudera 上的示例:

export PYCHBASE_INCLUDE_DIR=/home/matthew/libhbase/target/libhbase-1.0-SNAPSHOT/include

PYCHBASE_LIBRARY_DIR

这包含MapR 环境中的 libMapRClient.so 文件或非 MapR 环境中的libhbase.so文件

如果PYCHBASE_IS_MAPR为真,则默认为/opt/mapr/lib

对于非 MapR 环境,必须设置此项,否则安装将失败。

Cloudera 上的示例:

export PYCHBASE_LIBRARY_DIR=/home/matthew/libhbase/target/libhbase-1.0-SNAPSHOT/lib/native

作者

马修·莫伊森

执照

麻省理工学院

项目详情


下载文件

下载适用于您平台的文件。如果您不确定要选择哪个,请了解有关安装包的更多信息。

源分布

pychbase-0.1.8.tar.gz (32.6 kB 查看哈希

已上传 source