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

使用VSCode停止discord.py机器人时atexit模块失效求助

解决discord.py机器人退出时无法添加离线角色的问题

问题根源

  1. atexit和signal注册的回调是同步函数,但你的exit_handler是异步(async)方法,直接调用不会执行其中的await操作,异步代码根本没机会运行。
  2. 当通过VSCode/IDLE强制终止程序时,Discord客户端的事件循环可能已经提前关闭,导致异步操作无法执行。

修复方案

核心思路

将信号处理改为同步函数,在内部通过机器人的事件循环调度异步退出逻辑,同时确保客户端能正确完成收尾操作。

完整代码示例

import signal
import discord
from discord import utils

SERVER_ID = 你的服务器ID
BOT_USER_ID = 你的机器人ID

class MyClient(discord.Client):
    async def exit_handler(self):
        print("stopped!")
        # 仅在客户端就绪状态下执行角色操作
        if self.is_ready():
            guild = self.get_guild(SERVER_ID)
            if guild:
                role = utils.get(guild.roles, name="Bot Offline")
                member = guild.get_member(BOT_USER_ID)
                if role and member:
                    await member.add_roles(role)
        # 确保客户端正常关闭
        await self.close()

def handle_signal(signum, frame):
    # 利用机器人的事件循环执行异步退出任务
    if client.is_ready():
        client.loop.create_task(client.exit_handler())

# 初始化客户端(需根据需求配置intents)
client = MyClient(intents=discord.Intents.all())

# 注册终止信号处理
signal.signal(signal.SIGINT, handle_signal)
signal.signal(signal.SIGTERM, handle_signal)

# 启动机器人
client.run("你的机器人Token")

额外注意事项

  • 确保机器人拥有管理角色的权限,否则添加角色操作会静默失败。
  • 验证SERVER_ID和BOT_USER_ID的正确性,避免guild或member返回None。
  • 若通过系统服务(如systemd)运行机器人,SIGTERM信号会被正确触发,上述代码同样生效。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 12:12:36