Python
Darra AI SDK 的 Python 绑定。cffi 只走 ABI 模式(ffi.dlopen),不编译任何 C 扩展。只翻译 C ABI 的类型和错误码,零密码学、零容器格式逻辑。
权威契约:Core/include/darra_ai.h。语义冲突时以头文件为准。公开包是 runtime 构建:打开已签发的 .darmodel 做推理,不含加密 / 签发。
本文档对应 Python SDK v1.0.0(与 darra_ai.h 的 DARRA_VERSION_MAJOR/MINOR/PATCH 同一组数字,与 __version__ / pyproject.toml 一致)。加载 native 后立即核 ABI:darra_version() 的 major 必须等于 1,不等抛 DarraLoadError,禁止继续调用。客户机 version_string() 必须看到 1.0.0+runtime。
from darra_ai import Session
import darra_ai 不加载 native。第一次调用碰 Core 的 API(Session.open / diagnostics.collect / version())才 dlopen。
安装
pip install darra-ai
PyPI 分发名为 darra-ai(pip install 用此名),代码内导入名为 darra_ai(from darra_ai import Session)。两者是独立概念(PEP 427),不要混用。
- pip
- 开发树
- 指定 native 路径
依赖 cffi>=1.15。wheel 按平台内嵌 darra_ai/_native/<plat>/ 下的 native 库。缺 native 时第一次碰 Core 抛 DarraLoadError。
源码树 Darra.AI.Studio.SDK/Python/:
pip install -e .
需要 Python ≥ 3.10。本仓库未内嵌 native 时,get_lib() 抛 DarraLoadError,属预期。
找不到库时按顺序找:
- 包内
_native/<平台>/ - 环境变量
DARRA_AI_CORE_PATH(文件或目录) - 系统加载器搜索路径
平台目录名:win_amd64 / linux_x86_64 / linux_aarch64。
Windows 库名候选(按 _ffi 顺序):Core.dll、darraai_core.dll、DarraAI.Core.dll。Linux:libCore.so、Core.so、libdarraai_core.so、darraai_core.so。
原生库不在包内、也不在系统搜索路径时,设 DARRA_AI_CORE_PATH 指向文件或所在目录。SDK 按当前操作系统自动选对应平台的库名。
环境要求
| 项目 | 要求 |
|---|---|
| 操作系统 | Windows x64 / Linux x86_64 / Linux ARM64(RK3588)。macOS 不在 v1 |
| Python | ≥ 3.10(cffi ABI 模式,同一份纯 Python 不按解释器版本拆 wheel) |
| 依赖 | cffi ≥ 1.15 |
| native | DarraAI.Core(wheel 内嵌或 DARRA_AI_CORE_PATH) |
| 权限 | 装运行时包到系统目录时可能需要管理员;SDK 不代装 NVIDIA / RK3588 NPU 等系统驱动 |
| 不在 v1 | macOS、32 位 |
- 不承诺 dump 免疫。 授权机 + 管理员级调试器在会话存活期暂停 dump,挡不住。本 SDK 防的是静态拷走、转发、无授权运行、常规 dump 工具。
- 加密单向。 官方不提供解回明文的通道。激活码只用于打开 / 激活,推理不收激活码。
- 环境提前部署。 SDK 只验证和加载本地 Provider;下载、安装与系统驱动由 Studio 或部署流程处理,
diagnostics.collect提供只读诊断。 - macOS 不在 v1。 不是「即将支持」。
- Windows 无 RKNN。
edge-rknn只在 linux-arm64。Windows 上指名它抛UnsupportedPlatformError;Windows 收到 rknn 载荷抛UnsupportedPayloadError。 - 不承诺硬实时。 推理是阻塞调用。PLC 侧必须在扫描周期外进程 / 线程调用。
- 诊断 JSON 不含密钥 / 激活码 / token / 机器指纹字节。
功能概览
数据用属性,不用 get_xxx()。下表是常用入口(不列全量公开符号)。_ffi / _util 不是公开 API。本绑定没有 GRAY8 / RGBA8888 格式常量。
| 类别 | 属性 | 类型 | 访问 | 说明 |
|---|---|---|---|---|
| 版本 | version() | tuple[int, int, int] | 方法 | (major, minor, patch)。会加载 native |
version_string() | str | 方法 | 形如 1.0.0+runtime。会加载 native。客户机必须看到 +runtime | |
| 会话打开 | Session.open | Session | 类方法 | 打开已签发容器 .darmodel。不收激活码;指名 Provider 不可用 = fail-closed |
Session.open_plain | Session | 类方法 | 打开明文模型(.onnx / .pdmodel)。与 open 同一推理路径,只跳过容器解码与验票 | |
Session.open_ex | Session | 类方法 | 打开加密容器并传入 SessionOptions。走 darra_session_open_ex | |
Session.close | None | 方法 | 关闭会话。重复 close / 未打开均为 no-op。也实现 with 上下文 | |
| 会话元信息 | meta() | dict | 方法 | 会话元信息 JSON 对象(有缓存) |
task | str | None | 只读 | detect / classify / segment / pose / ocr / anomaly。缺席为 None | |
labels | list[str] | 只读 | 类别标签。缺席或非数组则为空列表 | |
input_width | int | 只读 | 模型输入宽。未知为 0 | |
input_height | int | 只读 | 模型输入高。未知为 0 | |
channels | int | 只读 | 模型输入通道数。未知为 0 | |
layout | str | None | 只读 | 张量布局(NCHW / NHWC)。先读 input.layout,再读顶层 layout | |
payload_kind | str | None | 只读 | onnx / trt-engine / openvino / rknn / paddle | |
provider_id | str | None | 只读 | 实际选中的 Provider ID(不是 prefer 入参) | |
encrypted | bool | 只读 | 是否容器会话。明文模型为 False | |
| 推理 | infer_image | dict | 方法 | 对一张图(一帧)跑推理,返回结果 JSON 对象。连续帧循环调用。不承诺硬实时 |
| 运行时 | diagnostics.collect | dict | 方法 | 本机环境自检 JSON。禁止在 PLC 扫描周期等实时路径调用 |
| 错误 | DarraError.code | int | None | 只读 | darra_error_code;绑定侧错误为 None |
DarraError.message | str | 只读 | 错误描述 | |
DarraError.hint | str | 只读 | 修复建议,与错误码目录逐字一致,可原样展示给最终用户 | |
DarraLoadError | DarraError | 抛出 | native 加载失败或 ABI 不匹配。code 恒为 None |
一模型一实例:一个 Session = 一份已加载模型 + 一个 Provider。多模型或多份同模型 = 多会话,API 完全相同。
快速开始
客户现场加载 .darmodel(新分发钥匙内嵌)。生产用 Session.open("model.darmodel")(已绑机)或出厂首启 Session.activate(...)(要一次激活码)。.darmkey 是旧双文件旁路,新分发的 .darmodel 钥匙内嵌,不要用。导出格式即加载格式,用户零配置。
from darra_ai import Session
with Session.open("model.darmodel") as s:
print(s.meta())
jpg = open("photo.jpg", "rb").read()
print(s.infer_image(jpg))
对应包未部署时返回缺包错误,请先准备环境再重试。环境准备的进度在 Studio 右上角下载中心查看。
失败时捕获 DarraError 子类,hint 即 错误码 给最终用户的修复建议:
from darra_ai import DarraError
try:
with Session.open("model.darmodel") as s:
s.infer_image(jpg)
except DarraError as ex:
print(ex) # [码] 描述 | 建议: hint
明文模型
与加密入口同一推理路径,只跳过容器解码与验票。路径可以是 .onnx、.pdmodel(同目录须有 .pdiparams)、或含二者的目录。.pt / .pth 仍拒,抛 UnsupportedPayloadError。
from darra_ai import Session
with Session.open_plain("model.onnx") as s:
print(s.infer_image(jpg))
.darmodel+ 授权 — 生产环境,推荐。open_plain— Studio 试跑 / 客户自有明文模型(含 Paddle 推理载荷)。
上下文管理器
Session 实现 __enter__ / __exit__,退出 with 块时自动 close()。
from darra_ai import Session
with Session.open("model.darmodel") as s:
print(s.task, s.labels)
print(s.infer_image(jpg))
完整脚本见 SDK 树 examples/infer_image.py。
工业相机裸缓冲
每次调用一张图(一帧)。相机循环里对每一帧再调一次。
from darra_ai import IMAGE_BGR888
result = s.infer_image(frame, format=IMAGE_BGR888, width=1920, height=1080)
裸缓冲禁止 IMAGE_AUTO(嗅探不出通道序)。stride=0 表示紧凑排列(RGB/BGR = width × 3)。
prefer_provider 指名但不可用 = fail-closed,绝不静默降级。
约定
惰性加载
import darra_ai 只引入纯 Python。第一次调用碰 Core 的 API 才 dlopen。结构测试与类型检查在无 dll 时也能 import。
加载后立即核 ABI:major ≠ 1 抛 DarraLoadError,禁止继续。
属性而非 getter
会话元信息走只读属性(s.task / s.labels / s.input_width …),全部从 meta() 的 JSON 派生。缺字段不编默认 640/80/17。
异常而非错误码
失败时抛 DarraError 子类。绑定把 C 的 int32_t 错误码翻译成异常;调用方不必自己调 darra_last_error。未知新码兜底为 DarraError 基类,code 原样保留。详见 错误。
encrypt_onnx / issue_key / fingerprint_perturb 只随 AI Studio 的 authoring 构建导出。客户机 runtime 包物理上没有这些符号;访问时抛 DarraError。公开文档不把它们当作 runtime API。
完整示例
from pathlib import Path
from darra_ai import IMAGE_AUTO, Session
from darra_ai.errors import DarraError
jpg = Path("photo.jpg").read_bytes()
try:
with Session.open("model.darmodel") as s:
print(s.task, s.payload_kind, s.provider_id)
print(s.infer_image(jpg, format=IMAGE_AUTO))
except DarraError as ex:
print(ex)