跳到主要内容

Safe API — 永不抛异常变体

概述

UI 主线程 / 批量轮询不希望被一条 RPC 失败抛出的 OpcUaException 中断, SDK 为常用调用各提供一个 *_safe 版本 — 任何异常折叠为 StatusCode, 调用方用 (status, value) 元组判读, 不再写 try/except

对应规范段: Browse Part 4 §5.8, Read §5.10.2, Write §5.10.4, Call §5.11.2, HistoryRead Part 11 §6.5。

API

方法类别读写说明
ua.browse_safe(node_id, filter)浏览返回 (StatusCode, list[OpcUaReference])
ua.read_safe(node_id, attribute)返回 (StatusCode, DataValue), 失败时 value=None
ua.write_safe(node_id, value, attribute)返回 StatusCode
ua.call_safe(object_id, method_id, *inputs)方法返回 (StatusCode, list[Variant])
ua.read_history_safe(node_id, t0, t1, max)历史返回 (StatusCode, list[DataValue])

代码示例

from opcua import DarraOpcUa, StatusCode, Variant

with DarraOpcUa("opc.tcp://localhost:4840") as ua:
ua.connect()

# 1) 浏览 - 节点删除不让全树报错
st, refs = ua.browse_safe("ns=2;s=Boiler1")
if st != StatusCode.GOOD:
print(f"Browse 失败 {st}, 跳过")
else:
for r in refs:
print(r.browse_name)

# 2) 批量轮询 - 单点失败不打断
for nid in node_list:
rs, dv = ua.read_safe(nid)
if rs == StatusCode.GOOD and dv is not None:
print(f"{nid} = {dv.value}")
else:
print(f"{nid} = <{rs}>")

# 3) 批量下发参数
for nid, val in setpoints.items():
rc = ua.write_safe(nid, Variant(val))
if rc != StatusCode.GOOD:
print(f"写 {nid} 失败 {rc}")

# 4) 调用方法
cst, outs = ua.call_safe("ns=2;s=Robot", "ns=2;s=Robot.Home")
if cst != StatusCode.GOOD:
print(f"Home 失败: {cst}")

# 5) 历史读
hst, vals = ua.read_history_safe("ns=2;s=Temp", t0, t1, max_values=5000)

与重试机制的关系

普通 read/write/browse/call/read_history 内部都包了 _retry_on_session_fault, session 级故障 (BadSessionClosed) 会自动重连一次。Safe 变体调用同一套核心方法, 也会受益于自动重连。

最佳实践

  • UI 主线程一律用 Safe — 异常逃逸会让进程挂掉
  • 批处理 / 巡检循环用 Safe — 单点失败不阻塞整体
  • 业务关键路径仍用普通版本, 让异常显式暴露

跨语言对照

C#PythonJavaC++RustC
BrowseSafebrowse_safebrowseSafeBrowseSafebrowse_safeDarraUa_Session_BrowseSafe
ReadSaferead_safereadSafeReadSaferead_safeDarraUa_Session_ReadSafe
WriteSafewrite_safewriteSafeWriteSafewrite_safeDarraUa_Session_WriteSafe
CallSafecall_safecallSafeCallSafecall_safeDarraUa_Session_CallSafe
ReadHistorySaferead_history_safereadHistorySafeReadHistorySaferead_history_safeDarraUa_Session_ReadHistorySafe

下一步