如何让ipywidget Button的on_click事件正常执行fabric-sdk-py异步方法
问题根因
- Jupyter 内核默认已运行一个 Asyncio 事件循环,直接调用
asyncio.run()或loop.run_until_complete()会触发This event loop is already running报错 - ipywidgets 的
on_click回调默认不支持直接接收异步函数,直接传入async def定义的函数会触发协程未被等待的报错
实现方案
正确做法是在同步回调函数中调用asyncio.create_task(),将异步协程提交到当前正在运行的 Jupyter 事件循环中调度执行,示例代码如下:
import asyncio # 异步业务逻辑,实现原本的交易查询逻辑 async def _check_id_async(b): x = await contract.evaluate_transaction('queryUnprotectedEntry', [_id_info.value], user) # 后续结果处理逻辑可直接写在这里,比如将返回结果赋值给页面展示组件 print(f"查询结果: {x.decode('utf-8')}") # 同步回调函数,作为on_click的绑定入口 def _check_id(b): # 提交异步任务到当前运行的事件循环 asyncio.create_task(_check_id_async(b)) # 绑定同步回调 _check_id_button.on_click(_check_id)
可选:异常捕获封装
如果需要捕获异步任务执行过程中的异常,可以增加一层协程包装逻辑:
async def _task_catch_wrapper(coro): try: await coro except Exception as e: # 自定义异常处理,比如输出错误信息到notebook print(f"交易执行失败: {str(e)}") def _check_id(b): asyncio.create_task(_task_catch_wrapper(_check_id_async(b)))
注意事项
- 不要手动关闭、停止 Jupyter 内核自带的事件循环,会导致整个 notebook 运行异常
- 异步函数中可以直接修改 ipywidget 组件的属性更新页面展示,不需要额外的调度逻辑
内容的提问来源于stack exchange,提问作者Fedor Petrov
相关产品推荐
相关产品推荐

