You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何停止通过runpy.run_module启动的discord.py模块且不关闭PyQt启动器?

解决discord.py从PyQt启动后独立停止、不关闭启动器的方案

核心逻辑是避免机器人的生命周期和启动器主进程/主循环强绑定,通过主动调用官方停止接口、隔离进程的方式实现独立控制。

场景1:GUI模式(cli=False,用qasync运行botLauncher())

你的现有代码已经捕获了协程取消异常,只要调整机器人实例的访问逻辑即可实现优雅停止:

  • 首先修改botLauncher()函数,将hangoutcore模块中初始化后的discord.py Bot实例暴露为可全局访问的变量,不要把启动逻辑完全封死在内部
  • 给PyQt界面上的停止按钮绑定异步槽函数,槽函数内主动调用await bot.close(),该方法是discord.py官方提供的优雅停止接口,会自动清理websocket连接、注销所有事件监听,调用后qasync.run()运行的协程会正常退出,不会影响PyQt主窗口的运行
  • 如果hangoutcore模块内用bot.run()启动,需要给该方法加close_loop=False参数,避免机器人停止时把qasync绑定的Qt事件循环一同关闭

示例调整代码:

# 先从hangoutcore模块暴露Bot实例
from hangoutcore import bot

async def botLauncher():
    # 原有启动逻辑:加载cog、初始化配置等
    await bot.start("你的机器人令牌")

# PyQt停止按钮的异步槽函数示例
async def stop_bot():
    if bot.is_ready():
        await bot.close()

场景2:CLI模式(cli=True,用runpy.run_module启动)

你当前用runpy运行模块是在主进程内执行,hangoutcore模块内bot.run()默认捕获到停止信号后会调用sys.exit(),直接带崩整个启动器进程,改法如下:

  • 放弃runpy方案,改用subprocess.Popen单独开子进程运行hangoutcore模块,停止时只需要终止子进程即可,完全不影响主启动器运行

示例调整代码:

import subprocess
import sys

# 启动子进程运行机器人
bot_subprocess = subprocess.Popen([sys.executable, "-m", "hangoutcore"])

# 停止机器人时调用该函数即可
def stop_cli_bot():
    bot_subprocess.terminate()
    bot_subprocess.wait()

注意事项

  • 不要通过给主进程发SIGINT信号模拟Ctrl+C的方式停止机器人,会直接终止整个启动器进程
  • 不要强行取消运行机器人的协程,使用bot.close()可以保证所有退出事件正常触发,不会出现资源泄漏

内容的提问来源于stack exchange,提问作者Lino

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.06 06:12:02