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秒):
to_wait3 = 14400 - 3600 = 10800秒,睡眠后发送1小时提醒(此时距目标还有3600秒)。- 接着执行
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
相关产品推荐
相关产品推荐

