质量与排错
并发与性能
| 事项 | 建议 |
|---|---|
| 后台线程 | daemon=True + Event 退出信号,on_disable 里 join |
| 定时器 | 用 threading.Event.wait(interval) 而不是 time.sleep,停用时能立刻响应 |
| 高频写存储 | 合并写入:set_many 或 transaction() |
| 高频推送界面 | 卡片/字段推送控制在秒级;毫秒级更新先做节流 |
| 外部命令 | 必须带 timeout(如 subprocess.run(..., timeout=6)),失败返回空而不是抛异常 |
| 外部命令输出 | stdout/stderr 走向不可假设,读取时两路合并最稳 |
| 阻塞操作 | 不要在 setup / 事件回调里做耗时操作;长任务放后台线程 |
| 异常处理 | 循环体整体包 try/except,一次异常不应终止整个轮询线程 |
def _loop(self):
while not self._stop.is_set():
try:
self._poll()
except Exception as e:
self.ctx.log.warning("轮询异常: %s", e) # 记日志,不退出
self._stop.wait(self._interval) # 可被立即唤醒调试手段
- 全流程用
ctx.log打点:加载、启用、每次轮询结果、异常。卡住先看宿主日志栏。 - 页面里用开发者工具(宿主窗口支持打开控制台)看
jade.call的报错。 - 逻辑复杂的模块,把纯函数(解析、计算)单独写成不依赖
ctx的部分,用普通 Python 脚本先测。 - 跨模块联调时,宿主的审计抽屉里有全部调用明细(来源、目标、结果),比翻日志快。
自测流程
- 把模块放进宿主的
modules/目录,启动宿主; - 看模块是否出现在列表、能否正常启用(加载失败时界面显示原因);
- 停用再启用一次,确认没有残留线程、没有重复定时器;
- 有界面的:在页面里逐个调用注册的方法,确认返回值与异常处理;
- 没界面的:用卡片区和底部字段条确认数据推上来了;
- 打包成
.jmod之后,把上面 1–5 步重跑一遍。源码能跑不等于打包后能跑。
常见问题
模块没出现在宿主列表里? 按顺序排查:manifest 字段是否合法(模块名小写字母开头,版本 x.y.z,不能有多余字段);入口文件是否存在且与 entry 一致;是否放在了 modules/ 里;看宿主日志的加载错误。
调用别的模块报"模块不可调用"? 目标模块不在"运行中"。启用它,或把它写进 dependencies 让宿主自动启用。
报"未注册处理器"? 方法名写错了,或目标模块的 setup() 里没注册。注册发生在 setup,不是 on_enable。
报"未在 dependencies 中声明依赖"? 宿主开了严格模式。manifest 的 dependencies 里加上目标模块名。
前端 jade.call 一直失败? 模块是否运行中;方法名/参数是否正确;返回值是否可 JSON 序列化;控制台看具体错误;是否超过 10 秒。前端调用固定 10 秒超时且页面里改不了,长任务改成「立即返回 + 后台执行 + 事件推送进度」。
页面 404 / 样式加载不出来? manifest 的 ui 路径写对没有;资源是否在 ui/ 或 assets/ 下;路径是否误写成 / 开头的绝对路径;打包后重新测过没有。
数据没保存? 确认用的是 ctx.store.set(...) 而不是自己写文件;键名一致;批量写入后进程被强杀可能丢最后一次写入。
停用模块后线程还在跑? on_disable 里没有正确停止。检查退出信号和 join,循环里是不是用了阻塞的 sleep。
加密打包后行为异常? 多半是资源没放在 ui//assets/ 下丢了,或模块内用 __file__ 推断路径(打包后不存在)。资源一律相对路径引用,运行时目录走 ctx.config 配置。
可以用 print() 调试吗? 界面上看不到。用 ctx.log.debug/info/warning/error。