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

如何使用atexit模块修复Discord机器人退出时的RuntimeWarning?

解决Discord机器人退出时发送Embed消息的RuntimeWarning问题

问题说明

我想给Discord机器人做一个退出处理器,让它每次离线时发送一条Embed消息。用atexit模块写了处理函数,但运行时出现以下警告:

/home/container/main.py:186: RuntimeWarning: coroutine 'Messageable.send' was never awaited
  final.send(embed=embed)
RuntimeWarning: Enable tracemalloc to get the object allocation traceback

尝试把处理函数改成async def后又引发了其他问题,求修复方法。

原代码

import atexit
# 其他discord.py相关导入...

def my_exit_handler():
    print("Exiting the program")
    time = get_current_timestamp() # 这个函数能正常工作
    embed = discord.Embed(
        title=" ",
        description=f"## 🔁 Bot is Restarting. Time now: <t:{time}> (<t:{time}:R>)",
        color=0x005300  # 绿色
    )
    channel_id = 1149359551464882229
    final = bot.get_channel(channel_id)
    final.send(embed=embed)
    save_thread_data() # 其他业务代码
    save_leaderboard_data() # 其他业务代码

# 主程序代码...

atexit.register(my_exit_handler)

bot.run('my token') 

解决方案

核心原因

final.send()是异步协程,必须用await调用,但atexit的回调是同步函数,没法直接用await;直接把处理函数改成async def后注册给atexit,协程也不会被执行,所以会报错。

推荐用以下两种方法解决:


方法1:使用discord.py自带的on_close事件(最推荐)

discord.py提供了on_close异步事件,会在机器人连接关闭时自动触发,完美适配异步操作:

# 先把处理函数改成异步函数
async def my_exit_handler():
    print("Exiting the program")
    time = get_current_timestamp()
    embed = discord.Embed(
        title=" ",
        description=f"## 🔁 Bot is Restarting. Time now: <t:{time}> (<t:{time}:R>)",
        color=0x005300  # 绿色
    )
    channel_id = 1149359551464882229
    final = bot.get_channel(channel_id)
    if final:  # 先检查频道是否存在,避免找不到频道报错
        await final.send(embed=embed)
    save_thread_data()
    save_leaderboard_data()

# 注册on_close事件
@bot.event
async def on_close():
    await my_exit_handler()

# 主程序代码...

# 不需要再用atexit.register了
bot.run('my token') 

方法2:如果必须用atexit(兼容其他退出场景)

如果还要处理非Discord触发的退出逻辑,需要手动获取异步事件循环,在同步回调里运行异步处理函数:

import asyncio
import atexit

# 异步处理函数
async def my_exit_handler():
    print("Exiting the program")
    time = get_current_timestamp()
    embed = discord.Embed(
        title=" ",
        description=f"## 🔁 Bot is Restarting. Time now: <t:{time}> (<t:{time}:R>)",
        color=0x005300  # 绿色
    )
    channel_id = 1149359551464882229
    final = bot.get_channel(channel_id)
    if final:
        await final.send(embed=embed)
    save_thread_data()
    save_leaderboard_data()

# 同步回调函数,用来调用异步处理函数
def sync_exit_handler():
    loop = asyncio.get_event_loop()
    # 如果事件循环还在运行,用create_task;如果已经关闭,重新创建并运行
    if loop.is_running():
        loop.create_task(my_exit_handler())
    else:
        loop.run_until_complete(my_exit_handler())

# 注册atexit回调
atexit.register(sync_exit_handler)

# 主程序代码...

bot.run('my token') 

注意:方法2可能存在事件循环已关闭的情况,不如方法1稳定,优先推荐方法1。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 13:53:16