.then is not called if previous event has cancels events

用户在 Gradio 5.13.1(Windows)中使用 gr.Textbox(stop_btn=True) 为聊天机器人添加停止按钮,希望通过 msg.stop() 取消正在进行的流式输出事件,并在取消后执行一个清理函数(如 stop_func )。当在 msg.stop(cancels=[su

.then is not called if previous event has cancels events

.then is not called if previous event has cancels events

快速结论:在 Gradio Blocks 中使用 Textbox 的 stop_btn 时,如果 .stop() 事件包含 cancels 参数且后续链式调用 .then(),则 .then() 中的回调函数不会被触发。优先检查是否在 .stop() 中同时指定了 cancelsfn.then(),可尝试将 .stop() 拆分为两次独立调用。

问题场景

用户在 Gradio 5.13.1(Windows)中使用 gr.Textbox(stop_btn=True) 为聊天机器人添加停止按钮,希望通过 msg.stop() 取消正在进行的流式输出事件,并在取消后执行一个清理函数(如 stop_func)。当在 msg.stop(cancels=[submit_event]) 后链式调用 .then(fn=stop_func) 时,stop_func 不会被调用。

报错原文

# 运行时无显式报错,但 stop_func 的 print 语句未输出
# 预期行为:按下停止按钮后,控制台应打印 "stop func called"
# 实际行为:控制台无任何输出,函数未执行

原因分析

根据 Issue 讨论,这是 Gradio 框架内部的事件调度问题。当一个 .stop() 事件同时包含 cancels 参数和后续 .then() 回调时,框架可能将取消动作与回调绑定在同一事件生命周期中,导致回调被意外跳过。可能原因包括:事件取消后后续链式事件未正确注册,或 cancels 参数的处理逻辑覆盖了 .then() 的依赖关系。

环境排查

  • Gradio 版本:确认是否为 5.13.1 或更新版本(5.x 系列)
  • 运行环境:Windows / Linux / macOS(Issue 中为 Windows)
  • 依赖检查:确保 Gradio 已正确安装,且无其他插件干扰事件系统

解决步骤

  1. (可优先尝试).stop() 事件拆分为两次独立调用:
    msg.stop(
        fn=None,
        cancels=[submit_event]
    )
    msg.stop(
        fn=stop_func,
        inputs=None,
        outputs=None
    )

    即第一次 .stop() 仅负责取消事件(不指定 fn.then()),第二次 .stop() 纯粹执行回调函数。这是 Issue 评论中验证有效的临时解决方案。

  2. 如果拆分后仍不生效,请检查 submit_event 变量是否确实指向 msg.submit(...).then(bot, chatbot, chatbot) 的返回值(应为事件链的末端)。
  3. 确保 bot 函数是生成器函数(yield),因为 cancels 取消生成器事件本身是正常用例。
  4. 如果问题依旧,可考虑在 stop_func 中手动调用 printgr.Info() 排除函数执行问题。

验证方法

运行修复后的代码,点击 Textbox 右侧的停止按钮(通常在输入框右侧),观察控制台是否打印 “stop func called”。同时确认聊天机器人的流式输出确实被取消(即输出中断)。如果回调函数执行且取消生效,则问题解决。

参考来源

gradio-app/gradio #10432

celebrityanime
celebrityanime
文章: 13451

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注