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

如何优雅捕获Ctrl+C信号并正常关闭Discord Py机器人

Discord.py机器人干净关机实现方案

核心问题说明

你写的bot.run()是同步阻塞方法,执行时会内部创建并运行事件循环,直到bot断开连接后才会退出,此时事件循环已经被关闭,无法直接在finally块中运行bot.close()这类协程对象。

推荐实现方案:手动管理事件循环

该方案支持完美捕获SIGINT/SIGTERM信号,按顺序执行自定义清理逻辑、卸载所有cog、关闭bot实例:

import asyncio
import signal
from discord.ext import commands

# 初始化bot,按需求配置前缀和Intents
bot = commands.Bot(command_prefix="!", intents=commands.Intents.all())
config = {"token": "你的机器人Token"}

async def shutdown_handler():
    """全局关机清理逻辑"""
    # 此处写入你的业务清理逻辑:比如更新数据库、关闭数据库连接、停止定时任务等
    print("正在执行关机前资源清理...")
    # 关闭bot,会自动触发所有已加载cog的cog_unload钩子
    await bot.close()

def signal_callback(signal_num, frame):
    """信号触发回调,向运行中的事件循环添加关机任务"""
    asyncio.create_task(shutdown_handler())

async def main():
    # 注册终止信号监听
    running_loop = asyncio.get_running_loop()
    for sig in (signal.SIGINT, signal.SIGTERM):
        running_loop.add_signal_handler(sig, signal_callback, sig, None)
    
    # 异步启动bot
    async with bot:
        await bot.start(config["token"])

if __name__ == "__main__":
    asyncio.run(main())

Cog单独清理逻辑配置

你只需要在每个Cog类中实现cog_unload异步方法,bot关闭时会自动执行所有Cog的该方法,实现每个模块的独立清理:

from discord.ext import commands

class CustomCog(commands.Cog):
    def __init__(self, bot):
        self.bot = bot
        # 例如该Cog持有独立的数据库连接、定时任务等资源

    async def cog_unload(self):
        """Cog卸载时自动触发的钩子"""
        # 写入当前Cog专属的清理逻辑,比如关闭连接、取消任务
        print(f"{self.__class__.__name__} 资源已清理完成")

async def setup(bot):
    await bot.add_cog(CustomCog(bot))

原有Try/Finally方案兼容修改

如果你不想修改原有结构,也可以在finally块中手动创建临时事件循环执行协程:

import asyncio

# 你的shutdown_handler改为异步方法
async def shutdown_handler():
    # 清理逻辑
    await bot.close()

try:
    bot.run(config["token"])
finally:
    # 手动拉起事件循环执行协程
    loop = asyncio.new_event_loop()
    asyncio.set_event_loop(loop)
    loop.run_until_complete(shutdown_handler())
    loop.close()

注意事项

  • 不要重复调用bot.close(),在全局清理逻辑中执行一次即可
  • 如果使用Discord.py v2.x版本,需要正确配置Intents权限,否则bot无法正常启动
  • 所有异步清理逻辑都需要放在异步函数内,通过事件循环调度执行

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 11:27:04