MisakaDB Python Client
作者:刘博源 这是 MisakaDB 的 Python 客户端文档,主要面向客户端调用方。
包名和导入名均为 misakadb,需要 Python 3.11 或更高版本。直接入口为 conn() 和 getCurrent();同时保留 MisakaDBClient、MiQL 等原有接口。客户端只依赖 Python 标准库。
功能概览
- 连接 MisakaDB 服务端
- 提供身份验证 (Login) 与安全拦截
- 获取服务信息与动态面板展示
- 执行文本命令
- 查询服务版本、网络配置、允许命令
- 自动发送心跳包
- 手动启动、停止心跳
- 查询心跳次数、失败次数、丢包率
目录
- 客户端 API:
misakadb/apis/api.py - 命令行入口:
misakadb/cli.py - 底层 socket 实现:
misakadb/network/sock.py - 命令格式化输出:
misakadb/network/command_send.py - 压测示例:
usage/demo1.py
构建与安装
从 PyPI 安装客户端:
python -m pip install misakadb
在仓库根目录安装源码包:
python -m pip install ./client
构建 wheel 和源码分发包(构建工具使用仓库已有的 uv):
uv build client --out-dir client/dist/packages
python -m pip install client/dist/packages/misakadb-0.2.1-py3-none-any.whl
已有 wheel 时可直接拷贝到其他机器,用 python -m pip install <wheel路径> 安装,无需访问包索引。发布目标为 PyPI 的 misakadb 项目,公开发布成功后可直接通过包名安装。
安装后可运行:
misakadb --version
misakadb --address 127.0.0.1 --port 10032 --mode shell
# 等价入口
python -m misakadb --address 127.0.0.1 --port 10032 --mode shell
使用虚拟环境时先激活环境;项目现有环境可用 source client/.venv/bin/activate。
Python SDK 链式 API(0.2.1)
0.2.0 开始,数据库与文档方法均只构造查询,必须调用 .shot() 才发送。0.1.x 的立即执行写法需要在末尾补上 .shot();conn() 建立连接、login() 登录和后台心跳仍立即执行。
import misakadb as misaka
with misaka.conn(ip="127.0.0.1", port=10032,
username="your_user", password="your_password") as conn:
cur = misaka.getCurrent()
# 已有数据库和表:保存作用域不会发请求。
table = cur.use("database01").table("table01")
table.join({"age": 23, "name": "Lisi"}).shot()
table.join({"age": 15, "name": "Lisit2", "studentID": 1}).shot()
print(table.show().magic("+studentID").shot())
# 成功执行显式作用域后,后续可复用当前 session。
cur.use().join({"name": "another"}).shot()
rows = cur.show().magic("+age", "$age>18").limit(100).shot()["data"]
cur.update().where({"name": "Lisi"}).new({"age": 24}).shot()
cur.remove().where({"name": "another"}).shot()
示例要求 database01/table01 已存在。cur.use("database01").table("table01").join({...}).shot() 也可一行执行,普通链只发送最后的操作一次。
useOrCreate:使用或创建数据库和表
# 直到 shot() 才发请求:库存在就使用,不存在就创建后使用。
cur.useOrCreate("example").shot()
# 0.2.1 支持「库.表」;单独调用时缓存待执行选择,下一次 shot() 完成创建和查询。
cur.useOrCreate("database01.table")
print(cur.show().magic("+studentID").shot())
# 也可直接链接插入,库和表不存在时都会创建。
cur.useOrCreate("example.people").join({"id": 1, "age": 20}).shot()
# 也可以延续建表链;此例要求 new_people 尚未创建。
cur.useOrCreate("example").createTable("new_people").shot()
# 已有表的插入也可链接。
cur.useOrCreate("example").table("people").join({"id": 1, "age": 20}).shot()
useOrCreate("database") 只处理数据库;useOrCreate("database.table") 同时处理库和表。限定名只允许一个点且两部分均非空;普通 use(database).table(name) 仍分别传入名称。直接在 cur 上调用 useOrCreate() 会缓存待执行计划,下一次从 cur 构造的查询自动携带它;构造、打印和检查查询都不发送请求,未调用 .shot() 时也不会创建任何对象。.shot() 成功后保存当前库表并消费计划,后续普通查询不会重复创建。保存的查询对象仍可独立复用,较早的查询不会清除更新的待执行选择。
沿用当前服务端协议:在 .shot() 内尝试建库并校验选择,指定表时再尝试建表并校验选择,最后执行链尾操作。仅忽略服务端明确的同名对象已存在错误。同名对象的并发创建由服务端数据库生命周期锁串行校验;其他错误(包括鉴权、权限、I/O 不确定)仍会抛出。每条连接共用当前选择;并发切换库表时应保存独立查询作用域或使用独立连接。
这是多个请求组成的流程,并非跨命令事务:若创建成功后链尾操作失败,新库、新表会保留。完整 .shot() 收到服务端错误时丢弃待执行选择、保留原客户端选择;本地参数校验失败不会发送请求,计划保留以便补全条件。断线或重新登录成功时清空选择计划。
构造、筛选和结果
use(database)选数据库,table(name)选表;use()不传参复用待执行选择或 session 的当前数据库和表。构造链不修改已确认的 session,显式选库/选表的链在.shot()成功后才缓存选择。- 查询对象不可变,可保存后分支复用。之后切换 session 不会改变已有查询的目标;
repr(query)、print(query)和query.miql不触发发送。 join(document=None)/join().new(document)构造插入;无参数join().shot()插入一个带自动 id 的文档。show().where({...}).magic("+age", "$age>18").limit(100).offset(0).shot()支持连续筛选。多个where/magic按 AND 合并,magic("$age")投影字段值。update().where({...}).new({...}).shot()和remove().magic("-age").shot()均可链接。全表修改显式使用.all()。- 原来的关键字筛选仍可构造查询,例如
show(where={"id": 1}, magic="+age")、update({"age": 21}, where={"id": 1})和remove(all=True),末尾均需.shot()。 .shot()返回 Python 字典:插入包含 id 和 affected;查询/更新/删除包含 data、matched、affected、revision、total 和 next_offset。读记录用result["data"]。- 每次
.shot()都执行一次请求,不自动缓存或重试写入。不要重复发送结果不确定的写操作。 getCurrent()的连接指针按线程/协程上下文保存;显式共享连接时,共用 session 和请求锁。conn.getCurrent()始终取得该连接的查询入口。- 未连接/断线时抛出
ConnectionError,服务端拒绝操作时抛出misaka.MisakaError,非法参数抛出ValueError。普通请求的错误只在.shot()发生。
table.query().show().where({...}).shot() 继续提供原生 MiQL 构造器,返回原始 bytes;它不接受尚待执行的 useOrCreate 计划。
原有 MiQL 构造接口
from misakadb import MisakaDBClient, MiQL, commandSend
with MisakaDBClient("127.0.0.1", 10032) as client:
# 使用服务端已有的用户名与密码。
if not commandSend(client.client).login("your_user", "your_password"):
raise PermissionError("登录失败")
mq = MiQL(client.client)
print(mq.useDB("test").shot().decode())
print(mq.createTable("people").shot().decode())
print(mq.join({"id": 1, "name": "御坂", "age": 20}).shot().decode())
print(mq.show().magic("$age>18").shot().decode())
print(mq.update().where({"id": 1}).new({"age": 21}).shot().decode())
print(mq.remove().where({"id": 1}).shot().decode())
示例要求数据库 test 已存在且表 people 尚未创建。已有表可用 mq.use("people").shot() 选择。原生 Python SDK 的字典键需要引号;Shell 字符串解析器允许不带引号的键。查询返回值保持现有的 bytes 协议格式,.shot() 执行请求,成功后的数据库和表选择保存在该连接的 session 中。
仓库中原有的 from apis.api import MisakaDBClient、from mql.MQ import MiQL 和 python client/misaka-cli.py 继续通过兼容入口使用同一份实现。安装包本身只提供 misakadb 命名空间。
快速开始
1. 创建客户端
from misakadb import MisakaDBClient
client = MisakaDBClient("127.0.0.1", 10032)
默认参数:
host="127.0.0.1"port=10032heartbeat_interval=1.0
2. 连接服务端与鉴权
ok = client.connect()
if not ok:
print("连接失败")
# 如果服务端开启了鉴权,需要发送 login 命令
# 在交互模式下,你可以使用 command_send 模块:
# command_send.login(username, password)
也可以指定重试参数:
ok = client.connect(retries=3, retry_delay=1.0)
3. 获取服务信息
service_info = client.get_service_info()
print(service_info)
典型返回值:
{
"network": {
"port": 10032,
"address": "0.0.0.0",
"max_conn": 2,
"retry_count": 3,
"retry_delay": 30
}
}
4. 关闭连接
client.close()
推荐写法
推荐使用上下文管理器,避免忘记关闭连接:
from misakadb import MisakaDBClient
with MisakaDBClient("127.0.0.1", 10032) as client:
info = client.get_service_info()
print(info)
API 说明
MisakaDBClient(host="127.0.0.1", port=10032, heartbeat_interval=1.0)
创建客户端对象。
参数说明:
host: 服务端地址port: 服务端端口heartbeat_interval: 心跳发送间隔,单位秒
注意:
- 初始化时会创建
client.heart心跳控制器 - 初始化时会启动心跳线程
- 真正发送心跳前仍要求连接已建立
connect(retries=3, retry_delay=1.0) -> bool
连接到服务端。
参数说明:
retries: 失败重试次数retry_delay: 重试间隔,单位秒
返回值:
True: 连接成功False: 连接失败
注:此方法仅负责底层 TCP 连接。如果需要身份验证,请在连接成功后调用 execute_command("login <user> <pass>") 或使用 commandSend.login()。
close() -> None
关闭当前连接,并停止当前心跳控制器。
get_service_info() -> dict | None
获取服务端信息。
成功时返回字典,失败时返回 None。
execute_command(command: str) -> str | dict | list | None
发送一条文本命令到服务端。
行为说明:
- 如果返回内容是 JSON,会自动解析成
dict或list - 如果返回内容不是 JSON,会返回字符串
- 如果请求失败,返回
None
示例:
result = client.execute_command("get-service-info")
print(result)
ping() -> bool
用于检查当前服务是否可达。
返回值:
True: 当前请求成功False: 当前请求失败
注意:
- 这里是业务层命令检测
- 不是底层 TCP keepalive
- 也不是服务端心跳回包确认
get_server_version() -> str | None
获取服务端版本号。
get_allowed_commands() -> list[str] | None
获取服务端允许的命令列表。
is_command_allowed(command: str) -> bool
检查某条命令是否被服务端允许。
get_network_config() -> dict | None
获取服务端网络配置。
心跳控制
客户端暴露了一个心跳控制对象:
client.heart
自动行为
MisakaDBClient初始化时会启动心跳线程connect()时会确保心跳处于启动状态- 已连接状态下,心跳线程会定时发送心跳帧
手动启动和停止
client.heart.start()
client.heart.stop()
说明:
start()启动或恢复心跳发送stop()停止发送心跳,但不会关闭连接
心跳统计字段
client.heart.count
client.heart.success_count
client.heart.failure_count
client.heart.loss_rate
client.heart.running
client.heart.last_error
client.heart.last_sent_at
字段说明:
count: 心跳发送尝试总次数success_count: 心跳发送成功次数failure_count: 心跳发送失败次数loss_rate: 当前统计口径下的失败率,单位百分比running: 当前是否处于启用状态last_error: 最近一次失败错误last_sent_at: 最近一次成功发送心跳的时间戳
获取完整统计
stats = client.heart.stats()
print(stats)
返回示例:
{
"running": True,
"interval": 10.0,
"count": 12,
"success_count": 12,
"failure_count": 0,
"loss_rate": 0.0,
"last_error": None,
"last_sent_at": 1710000000.123
}
关于“丢包率”的说明
当前协议没有单独的心跳响应包,因此这里的“丢包率”并不是网络层真实丢包率,而是:
心跳发送失败次数 / 心跳发送尝试总次数
如果后续服务端增加了心跳应答包,这里的统计口径可以再升级为真正的收发确认率。
命令行交互模式 (CLI)
客户端提供了一个功能丰富的交互式终端入口 (misakadb 命令),支持以下特性:
- 密码回显关闭:安全的密码输入体验(与 Linux 终端一致)
- 华丽面板:针对
get-service-info等特殊命令提供了对齐的 JSON 展平和 Misaka ASCII Logo 渲染 - 自动耗时统计:所有命令自动显示执行延迟 (绿色 < 0.2ms,黄色 >= 0.2ms)
- 多行输入:支持以
\结尾进行多行命令拼接
启动 CLI
misakadb --address 127.0.0.1 --port 10032 --mode shell
可选参数:
--username <name>: 预设用户名--password <pass>: 预设密码--mode onlyConn: 仅建立连接测试,跳过交互式终端 (适合作为 Windows 后台服务启动)
完整示例
from misakadb import MisakaDBClient
with MisakaDBClient("127.0.0.1", 10032, heartbeat_interval=5.0) as client:
info = client.get_service_info()
print("服务信息:", info)
print("服务版本:", client.get_server_version())
print("网络配置:", client.get_network_config())
print("允许命令:", client.get_allowed_commands())
print("心跳是否运行:", client.heart.running)
print("心跳次数:", client.heart.count)
print("心跳失败率:", client.heart.loss_rate)
client.heart.stop()
print("手动停止心跳:", client.heart.running)
client.heart.start()
print("重新启动心跳:", client.heart.running)
result = client.execute_command("get-service-info")
print("命令结果:", result)
注意事项
execute_command()和心跳发送共用同一个 socket,并通过锁保证不会交叉写入- 当前客户端是长连接模型,建议复用连接,不要高频短连接压测
- 如果你要做压测,优先参考
usage/demo1.py的“单连接多请求”模式 - 如果服务端返回的内容不是合法 JSON,客户端会自动退回为字符串返回
Metadata
Release files for misakadb 0.2.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| misakadb-0.2.1.tar.gz | 34.7 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| misakadb-0.2.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 64.1 kB
Release files / misakadb-0.2.1.tar.gz
| Download URL | misakadb-0.2.1.tar.gz |
|---|---|
| Size | 34.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
b4d800c4e07bb37c12fc3e77fe758fabdae39ceae3d0316809904db0c29a308f
|
|
BLAKE2b-256 checksum How to use checksums |
85e14053457c27659632edfe475cab1590c6c32a6ef1d17444ba84a4a84478fd
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.13
|
Release files / misakadb-0.2.1-py3-none-any.whl
| Download URL | misakadb-0.2.1-py3-none-any.whl |
|---|---|
| Size | 29.4 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
2ccafc60ea9142501610628564d5c2499ee2396ce69c87d42da9d48e969ead01
|
|
BLAKE2b-256 checksum How to use checksums |
1f29502e29b819df6fc05e66dd7b06414a9a314a253ba0f3fdf0fe0d0373a8e1
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.13
|
Security for misakadb 0.2.1
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.