HugeGraph Python 客户端快速上手
hugegraph-python-client 是 HugeGraph 的 Python SDK,可管理 Schema、读写图数据并执行 Gremlin 查询。HugeGraph-LLM 和 HugeGraph-ML 也使用这个客户端。
该模块位于 hugegraph-ai 仓库的 hugegraph-python-client/ 目录下,导入名为 pyhugegraph。
环境要求
- 客户端与 HugeGraph-AI workspace 均要求 Python 3.10 或更高版本,CI 在 3.10 和 3.11 上运行客户端测试。
- HugeGraph Server 1.5.0 或更高版本。客户端会拒绝连接更低版本的 Server,此类场景请改用 v1.3.x 客户端。
uv(推荐)或 pip
运行时依赖为 decorator、requests、setuptools、urllib3 和 rich。
安装
发布到 PyPI 的发行包名是 hugegraph-python:
1uv pip install hugegraph-python
2# 也可以使用 pip install hugegraph-python
上述命令不固定版本号,默认安装最新发布版;发行信息见 PyPI 发布页。源码目录名是 hugegraph-python-client,发行包名为 hugegraph-python;需要主线代码时,请从 HugeGraph-AI workspace 安装。
如需使用仓库中的最新代码,请从 HugeGraph-AI 仓库根目录同步 workspace。hugegraph-python-client 是 workspace 成员,通过 python-client extra 暴露,因此仅执行 uv sync 不会安装它:
1git clone https://github.com/apache/hugegraph-ai.git
2cd hugegraph-ai
3uv sync --extra python-client
4source .venv/bin/activate
连接并写入数据
1from pyhugegraph.client import PyHugeClient
2
3client = PyHugeClient(
4 url="http://127.0.0.1:8080",
5 graph="hugegraph",
6 user="admin",
7 pwd="admin",
8 graphspace=None,
9)
10
11schema = client.schema()
12schema.propertyKey("name").asText().ifNotExist().create()
13schema.propertyKey("birthDate").asText().ifNotExist().create()
14schema.vertexLabel("Person").properties("name", "birthDate") \
15 .usePrimaryKeyId().primaryKeys("name").ifNotExist().create()
16schema.vertexLabel("Movie").properties("name") \
17 .usePrimaryKeyId().primaryKeys("name").ifNotExist().create()
18schema.edgeLabel("ActedIn").sourceLabel("Person").targetLabel("Movie") \
19 .ifNotExist().create()
20
21graph = client.graph()
22person = graph.addVertex(
23 "Person", {"name": "Al Pacino", "birthDate": "1940-04-25"}
24)
25movie = graph.addVertex("Movie", {"name": "The Godfather"})
26edge = graph.addEdge("ActedIn", person.id, movie.id, {})
27
28print(graph.getVertexById(person.id))
29print(graph.getEdgeById(edge.id))
30graph.close()
客户端参数
PyHugeClient(url, graph, user, pwd, graphspace=None, timeout=None)
每个 HTTP 会话在收到 500、502、504 响应时会重试 3 次,退避因子为 0.1。
Server 版本与 GraphSpace
客户端在构造时解析 GraphSpace:
- 传入非空的
graphspace 字符串时直接开启 GraphSpace 模式。 - 否则客户端会请求
GET {url}/versions 并读取 versions.core。 - Server 版本低于 1.5.0 时抛出
RuntimeError,提示升级 Server 或改用 v1.3.x 客户端。 - Server 版本高于 1.5.0 时会把
graphspace 设为 DEFAULT 并开启 GraphSpace 模式,同时在日志中打印警告。版本恰好为 1.5.0 时保持关闭。 - 若因网络原因探测失败,GraphSpace 模式保持关闭。
该模式决定请求前缀:开启时为 /graphspaces/<graphspace>/graphs/<graph>/...,关闭时为 /graphs/<graph>/...。
客户端提供的 Manager
每个访问器都会惰性创建对应的 Manager,并为其分配独立的 HTTP 会话。
pyhugegraph.api 中还提供了 RankManager、RebuildManager 和 ServicesManager,但 PyHugeClient 暂未提供对应的访问器,需要时可自行传入 session 构造。
常用操作
构建 Schema
Schema 构建器采用链式调用,最后调用 create(),也可以用 append()、eliminate() 和 remove() 修改已有定义。
1schema = client.schema()
2
3# 属性类型:asText/asInt/asLong/asFloat/asDouble/asBool/asByte/asBlob/asDate/asObject
4# 基数:valueSingle/valueList/valueSet
5# 聚合:calcMax/calcMin/calcSum/calcOld
6schema.propertyKey("age").asInt().valueSingle().ifNotExist().create()
7
8# 顶点标签 ID 策略:useAutomaticId/useCustomizeStringId/useCustomizeNumberId/usePrimaryKeyId
9schema.vertexLabel("person").properties("name", "age", "city") \
10 .primaryKeys("name").nullableKeys("city").ifNotExist().create()
11
12# 边标签:link() 等价于 sourceLabel() 加 targetLabel()
13schema.edgeLabel("knows").link("person", "person").multiTimes() \
14 .properties("date", "city").sortKeys("date").nullableKeys("city") \
15 .ifNotExist().create()
16
17# 索引标签:先 onV/onE,再选择 secondary/range/search/shard/unique
18schema.indexLabel("personByCity").onV("person").by("city") \
19 .secondary().ifNotExist().create()
查询 Schema
1schema = client.schema()
2print(schema.getSchema()) # 完整 Schema,format 默认为 json
3print(schema.getPropertyKeys())
4print(schema.getVertexLabels())
5print(schema.getEdgeLabels())
6print(schema.getIndexLabels())
7
8# 查询单个定义
9print(schema.getPropertyKey("name"))
10print(schema.getVertexLabel("person"))
11print(schema.getEdgeLabel("knows"))
12print(schema.getIndexLabel("personByCity"))
13
14# 边标签的连接关系,格式形如 Person--ActedIn-->Movie
15print(schema.getRelations())
读取、更新和删除图数据
图接口直接接收属性字典,不支持链式的属性构建器:
1graph = client.graph()
2graph.appendVertex(person.id, {"birthDate": "1940-04-25"}) # 追加属性
3graph.eliminateVertex(person.id, {"birthDate": "1940-04-25"}) # 删除属性
4graph.appendEdge(edge.id, {"city": "Beijing"})
5graph.eliminateEdge(edge.id, {"city": "Beijing"})
6graph.removeEdgeById(edge.id)
7graph.removeVertexById(person.id)
8graph.close()
addVertex 返回 VertexData,包含 id、label、type 和 properties。addEdge 返回 EdgeData,包含 id、label、type、outV、outVLabel、inV、inVLabel 和 properties。
传给客户端的顶点 ID 可以是字符串、整数或 uuid.UUID。布尔值会被拒绝,整数必须落在 Java signed long 范围内。
批量写入
addVertices 接收 (label, properties) 二元组,addEdges 接收 (label, out_id, in_id, out_label, in_label, properties) 六元组。两者返回的对象只携带生成的 ID。
1graph = client.graph()
2vertices = graph.addVertices([
3 ("person", {"name": "Alice", "age": 20}),
4 ("person", {"name": "Bob", "age": 23}),
5])
6edges = graph.addEdges([
7 ("knows", vertices[0].id, vertices[1].id, "person", "person", {"date": "2012-01-10"}),
8])
分页与条件查询
1graph = client.graph()
2
3# 返回 (vertices, next_page),把 next_page 传回即可继续翻页
4vertices, next_page = graph.getVertexByPage("person", limit=10)
5vertices, next_page = graph.getVertexByPage("person", limit=10, page=next_page)
6
7# 服务端属性条件
8older = graph.getVertexByCondition("person", properties={"age": "P.gt(29)"})
9
10# 边分页查询,传入 vertex_id 时必须同时传 direction
11edges, next_page = graph.getEdgeByPage(label="knows", limit=10)
12edges, next_page = graph.getEdgeByPage(vertex_id=person.id, direction="OUT", limit=10)
13
14# 按 ID 批量查询
15graph.getVerticesById([v1.id, v2.id])
16graph.getEdgesById([e1.id, e2.id])
执行 Gremlin
1gremlin = client.gremlin()
2result = gremlin.exec("g.V().limit(5)")
3print(result)
exec 会根据图名称和解析出的 GraphSpace 自动绑定 graph 与 g 别名,并返回服务端响应中的 result 字段。响应缺少 requestId、status 或 result 时抛出 ResponseParseError。
图遍历
TraverserManager 封装了 Server 的 traverser 接口,方法名使用蛇形命名。
1traverser = client.traverser()
2
3traverser.k_out(marko_id, 2)
4traverser.k_neighbor(marko_id, 2)
5traverser.same_neighbors(marko_id, josh_id)
6traverser.jaccard_similarity(marko_id, josh_id)
7traverser.shortest_path(marko_id, ripple_id, 3)
8traverser.all_shortest_paths(marko_id, ripple_id, 3)
9traverser.weighted_shortest_path(marko_id, ripple_id, "weight", 3)
10traverser.single_source_shortest_path(marko_id, 2)
11traverser.multi_node_shortest_path([marko_id, josh_id], max_depth=2)
12traverser.paths(marko_id, josh_id, 2)
13traverser.crosspoints(marko_id, josh_id, 2)
14traverser.rings(marko_id, 3)
15traverser.rays(marko_id, 2)
16traverser.vertices(marko_id)
17traverser.edges(edge_id)
基于 POST 的接口需要传入请求体:advanced_paths、customized_paths、template_paths、customized_crosspoints 和 fusiform_similarity。
图变量
1variable = client.variable()
2variable.set("owner", "mary")
3print(variable.get("owner"))
4print(variable.all())
5variable.remove("owner")
异步任务
1task = client.task()
2print(task.list_tasks(status="success", limit=10))
3print(task.get_task(task_id))
4task.cancel_task(task_id)
5task.delete_task(task_id)
Server 指标与图信息
1metrics = client.metrics()
2metrics.get_all_basic_metrics()
3metrics.get_gauges_metrics()
4metrics.get_counters_metrics()
5metrics.get_histograms_metrics()
6metrics.get_meters_metrics()
7metrics.get_timers_metrics()
8metrics.get_statistics_metrics()
9metrics.get_system_metrics()
10metrics.get_backend_metrics()
11
12graphs = client.graphs()
13graphs.get_all_graphs()
14graphs.get_version()
15graphs.get_graph_info()
16graphs.get_graph_config()
17graphs.clear_graph_all_data() # 删除全部顶点、边和 Schema
18
19print(client.version().version())
认证与授权
AuthManager 与 Server 的路由保持一致:用户、资源、归属和权限挂载在 /graphspaces/{graphspace}/auth/... 下,用户组仍在 Server 级别的 /auth/groups。在 HugeGraph 1.7.0 及以上版本必须能解析出 graphspace,否则这些调用会在发出请求前抛出 ValueError。
1auth = client.auth()
2
3user = auth.create_user("test_user", "password")
4auth.modify_user(user["id"], user_email="hugegraph@apache.org")
5auth.get_user(user["id"])
6auth.list_users(limit=10)
7auth.delete_user(user["id"])
8
9group = auth.create_group("test_group", "read only")
10auth.modify_group(group["id"], group_description="updated")
11auth.list_groups()
12auth.delete_group(group["id"])
13
14target = auth.create_target("target1", "hugegraph", "127.0.0.1:8080", [])
15auth.update_target(target["id"], "target1", "hugegraph", "127.0.0.1:8080", [])
16auth.list_targets()
17auth.delete_target(target["id"])
18
19belong = auth.create_belong(user["id"], group["id"])
20auth.update_belong(belong["id"], "description")
21auth.list_belongs()
22auth.delete_belong(belong["id"])
23
24access = auth.grant_accesses(group["id"], target["id"], "READ")
25auth.modify_accesses(access["id"], "description")
26auth.list_accesses()
27auth.revoke_accesses(access["id"])
方法命名
Manager 中以驼峰命名的方法(例如 addVertex、getVertexById)会在构造时自动生成蛇形命名别名,graph.add_vertex(...) 与 graph.addVertex(...) 指向同一个方法。驼峰写法已在 debug 日志中标记为废弃,新代码建议使用蛇形命名。
错误处理
异常定义在 pyhugegraph.utils.exceptions 中:
请求体与响应体写入日志时,会对密码、token 和 secret 等字段做脱敏处理。
1from pyhugegraph.utils.exceptions import NotFoundError
2
3try:
4 graph.getVertexById("no-such-id")
5except NotFoundError:
6 print("vertex missing")
接口参数会随 HugeGraph REST API 版本变化。遇到不兼容时,先核对当前 Server 的 REST API 文档与客户端测试用例。
开发检查
在 HugeGraph-AI 仓库根目录运行格式与静态检查:
1./style/code_format_and_analysis.sh
按照 CI 的方式运行测试:
1# 单元测试与契约测试,无需 Server
2uv run pytest hugegraph-python-client/src/tests -m "unit or contract"
3
4# 集成测试,需要可访问的 Server
5HUGEGRAPH_URL=http://127.0.0.1:8080 \
6HUGEGRAPH_GRAPH=hugegraph \
7HUGEGRAPH_USER=admin \
8HUGEGRAPH_PASSWORD=admin \
9uv run pytest hugegraph-python-client/src/tests -m "integration and hugegraph"
CI 的集成测试作业使用 hugegraph/hugegraph:1.7.0 镜像。需要非默认空间时,还可以设置 HUGEGRAPH_GRAPHSPACE。
源码与测试位于 hugegraph-python-client/src/pyhugegraph/ 和 hugegraph-python-client/src/tests/,可直接运行的示例在 hugegraph-python-client/src/pyhugegraph/example/hugegraph_example.py。