Skip to content

Complete runnable example / 完整示例

Documentation home · 中文手册 · More recipes

This page is the maintained standalone example for the documentation-only release. Copy the Python block below into a local file named docs_quickstart.py. It does not require changes to the driver source. Do not substitute the repository's legacy root-level example script, which is not updated by this documentation release.

Before running

  • Install hbase-driver with python -m pip install hbase-driver; venv is optional.
  • Use a development cluster with simple authentication and the default /hbase znode.
  • Ensure ZooKeeper and the advertised Master/RegionServer names are reachable.
  • The script creates a unique default:docs_demo_* table with the cf family. It removes only that table after successful creation, even when a later operation fails.
  • If creation times out, inspect the printed name before deciding whether to clean up: the server may have created the table despite the error.
  • Run without Python -O, because this verification uses assertions.

中文:把下面代码保存为 docs_quickstart.py,在测试集群运行。代码会创建唯一临时表,完成验证后清理;不会删除预先存在的业务表。只导入文件不会连接集群。

Run locally or in the project container

For a cluster reachable from your Python environment:

HBASE_ZK=127.0.0.1:2181 python docs_quickstart.py

On Windows PowerShell:

$env:HBASE_ZK = "127.0.0.1:2181"
python docs_quickstart.py

If you use this repository's Docker environment, save the file in the checkout (keep this local scratch file untracked), then run:

docker compose up -d
docker compose exec -T dev python docs_quickstart.py
docker compose stop

The dev service is this project's hbase_dev; HBASE_ZK is already set to hbase-zk:2181. Do not use another project's container. Stopping preserves the data volume.

Copyable script

"""Run a small, disposable HBase demonstration.

Use HBASE_ZK to select the cluster. Importing this module does not connect or
modify data. Running it creates a unique default:docs_demo_* table, then removes
only that table after successful creation. Use a development cluster.
"""
from __future__ import annotations

import os
from uuid import uuid4

from hbasedriver.client.buffered_mutator import BufferedMutator, BufferedMutatorParams
from hbasedriver.client.client import Client
from hbasedriver.common.table_name import TableName
from hbasedriver.filter import (
    BinaryComparator,
    CompareOperator,
    FilterList,
    PrefixFilter,
    SingleColumnValueFilter,
)
from hbasedriver.hbase_constants import HConstants
from hbasedriver.operations.batch import BatchGet, BatchPut
from hbasedriver.operations.column_family_builder import ColumnFamilyDescriptorBuilder
from hbasedriver.operations.delete import Delete
from hbasedriver.operations.get import Get
from hbasedriver.operations.increment import CheckAndPut, Increment
from hbasedriver.operations.put import Put
from hbasedriver.operations.scan import Scan


def run_demo(zk_quorum: str) -> bytes:
    """Verify core operations and return the name of the cleaned-up table.

    Exceptions propagate, including cleanup errors. If create_table times out,
    inspect the printed name: the server may have created it despite the error.
    """
    if not __debug__:
        raise RuntimeError("Run this verification example without Python -O.")
    name = TableName.value_of(
        b"default", f"docs_demo_{uuid4().hex}".encode("ascii")
    )
    print(f"Using disposable table {name}", flush=True)
    created = False
    with Client({HConstants.ZOOKEEPER_QUORUM: zk_quorum}) as client:
        with client.get_admin() as admin:
            try:
                admin.create_table(
                    name, [ColumnFamilyDescriptorBuilder(b"cf").build()]
                )
                created = True
                descriptor = admin.describe_table(name)
                assert len(descriptor.table_schema) == 1
                schema = descriptor.table_schema[0]
                assert [family.name for family in schema.column_families] == [b"cf"]
                with client.get_table(name.ns, name.tb) as table:
                    table.put(
                        Put(b"user:001")
                        .add_column(b"cf", b"name", "张三".encode("utf-8"))
                        .add_column(b"cf", b"state", b"active")
                    )
                    row = table.get(Get(b"user:001"))
                    assert row is not None
                    assert row.get(b"cf", b"name").decode("utf-8") == "张三"

                    filters = FilterList(
                        operator=FilterList.Operator.MUST_PASS_ALL,
                        filters=[
                            PrefixFilter(b"user:"),
                            SingleColumnValueFilter(
                                b"cf", b"state", CompareOperator.EQUAL,
                                BinaryComparator(b"active"),
                                filter_if_missing=True,
                                latest_version_only=True,
                            ),
                        ],
                    )
                    scan = (
                        Scan(start_row=b"user:")
                        .with_end_row(b"user;", inclusive=False)
                        .add_family(b"cf")
                        .set_filter(filters)
                    )
                    with table.scan(scan) as scanner:
                        rows = scanner.next_batch(10)
                    assert [item.rowkey for item in rows] == [b"user:001"]

                    writes = BatchPut()
                    writes.add_put(Put(b"batch:1").add_column(b"cf", b"value", b"A"))
                    writes.add_put(Put(b"batch:2").add_column(b"cf", b"value", b"B"))
                    write_results = table.batch_put(writes)
                    assert write_results == [True, True]
                    reads = BatchGet([b"batch:1", b"batch:2"])
                    reads.add_column(b"cf", b"value")
                    results = table.batch_get(reads)
                    assert results[b"batch:1"].get(b"cf", b"value") == b"A"
                    assert results[b"batch:2"].get(b"cf", b"value") == b"B"

                    count = table.increment(
                        Increment(b"counter:1").add_column(b"cf", b"count", 1)
                    )
                    assert count == 1
                    claim = CheckAndPut(b"job:1")
                    claim.set_check(b"cf", b"state", None)
                    claim.set_put(Put(b"job:1").add_column(b"cf", b"state", b"claimed"))
                    first_claim = table.check_and_put(claim)
                    second_claim = table.check_and_put(claim)
                    assert first_claim is True
                    assert second_claim is False

                    params = BufferedMutatorParams()
                    params.write_buffer_periodic_flush = 0
                    with BufferedMutator(table, params) as mutator:
                        mutator.mutate(
                            Put(b"buffer:1").add_column(b"cf", b"value", b"saved")
                        )
                        mutator.flush()
                    buffered = table.get(Get(b"buffer:1"))
                    assert buffered is not None
                    assert buffered.get(b"cf", b"value") == b"saved"

                    table.delete(Delete(b"batch:1"))
                    assert table.get(Get(b"batch:1")) is None
            finally:
                if created:
                    admin.disable_table(name)
                    admin.delete_table(name)
    print(f"Core examples passed; removed {name}", flush=True)
    return name.tb


if __name__ == "__main__":
    run_demo(os.getenv("HBASE_ZK", "127.0.0.1:2181"))

The last line starts with Core examples passed; removed default:docs_demo_, followed by the unique table name. This verifies basic schema inspection, CRUD, filtering, batch result shapes, counters, conditional writes, and buffered writes. JSON, pagination, Append, and RowMutations have separate recipes.

A passing example is not a production compatibility guarantee. See current limitations before relying on time ranges, multiple versions, concurrency, secure authentication, or Region failover.