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

Discord提醒Bot中asyncio.sleep超时异常问题求助

Discord提醒机器人延迟问题分析与修复

问题现象

设置未来数小时的提醒时,1小时前的通知能正常发送,但5分钟前和即时通知会出现大幅延迟,甚至晚数小时送达。

核心原因

代码中asyncio.sleep()的参数逻辑错误,导致后续睡眠时长叠加后远超预期:

  • 第一个await asyncio.sleep(to_wait3)是正确的,它计算的是当前时间到1小时提醒点的等待时长(目标时间减3600秒减去当前时间戳)。
  • 但第二个await asyncio.sleep(to_wait2)误用了to_wait - 300,这是当前时间到5分钟提醒点的总时长,而非1小时提醒点到5分钟提醒点的间隔时长。
  • 第三个await asyncio.sleep(to_wait)直接使用总等待时长,进一步加剧了延迟。

举个实际数值例子:若目标时间距当前4小时(14400秒):

  1. to_wait3 = 14400 - 3600 = 10800秒,睡眠后发送1小时提醒(此时距目标还有3600秒)。
  2. 接着执行await asyncio.sleep(14400-300=14100),累计睡眠时长达到10800+14100=24900秒,比目标时间晚了10500秒(近3小时)。

修复代码

将后续睡眠参数改为相邻提醒节点的时间间隔,同时优化时间计算逻辑:

from datetime import datetime, timedelta, timezone
import asyncio
import discord

@bot.command()
async def cfgr(ctx, ac: str, date: str, time: str):
    # 清理同名旧配置
    for k in list(acdict.keys()):
        if k == ac:
            del acdict[k]
    ac_date = f"{date} {time}"
    acdict[ac] = ac_date
    
    # 解析目标时间并转为UTC时区
    target_time = datetime.strptime(ac_date, "%Y-%m-%d %H:%M").replace(tzinfo=timezone.utc)
    now = datetime.now(timezone.utc)
    
    # 定义各提醒节点
    one_hour_before = target_time - timedelta(hours=1)
    five_min_before = target_time - timedelta(minutes=5)
    
    # 发送配置成功通知
    embed = discord.Embed(title="已配置")
    embed.add_field(name=f"{ac} 提醒时间:", value=target_time.strftime("%Y-%m-%d %H:%M UTC"))
    await ctx.send(embed=embed)
    
    # 1小时前提醒
    if one_hour_after_now := (one_hour_before - now).total_seconds() > 0:
        await asyncio.sleep(one_hour_after_now)
        embed = discord.Embed(title="提醒")
        embed.add_field(name=f"{ac} 还有1小时开始!", value="")
        await ctx.send(content=f"{ctx.message.guild.default_role}", embed=embed)
    
    # 从1小时提醒到5分钟提醒的间隔
    if five_min_after_one_hour := (five_min_before - one_hour_before).total_seconds() > 0:
        await asyncio.sleep(five_min_after_one_hour)
        embed = discord.Embed(title="提醒")
        embed.add_field(name=f"{ac} 还有5分钟开始!", value="")
        await ctx.send(content=f"{ctx.message.guild.default_role}", embed=embed)
    
    # 从5分钟提醒到即时提醒的间隔
    if now_after_five_min := (target_time - five_min_before).total_seconds() > 0:
        await asyncio.sleep(now_after_five_min)
        embed = discord.Embed(title="提醒")
        embed.add_field(name=f"{ac} 现在开始了!", value="")
        await ctx.send(content=f"{ctx.message.guild.default_role}", embed=embed)

额外优化点

  • 增加对等待时长的非负判断,避免设置过去时间时触发无效睡眠。
  • 使用timedelta计算时间差,代码可读性更强,减少手动计算秒数的错误。
  • 若需要管理大量定时任务,建议引入APScheduler等任务调度库,避免长时间占用协程影响机器人其他功能响应。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 11:14:55