Discord.py中Barrel计时器取消命令失效问题求助
问题分析与解决方案
你的代码核心问题在于每次命令调用的ctx是全新的实例,在barrels命令里给ctx.task赋值的任务,到barrelsc命令里的ctx对象根本访问不到,自然无法取消计时器。
修正方案
我们需要用一个全局容器(比如字典)来存储活跃的计时器任务,把用户ID作为键,这样跨命令就能找到对应的任务。
完整修正代码
import asyncio import discord from discord.ext import commands client = commands.Bot(command_prefix="!", intents=discord.Intents.all()) # 全局字典存储活跃计时器,键为用户ID,值为对应的asyncio.Task对象 active_barrel_tasks = {} @client.command() async def barrels(ctx, member: discord.Member = None): target_member = member or ctx.author user_id = target_member.id # 检查用户是否已有活跃计时器 if user_id in active_barrel_tasks and not active_barrel_tasks[user_id].done(): await ctx.send(f"{target_member.mention} 已经有一个正在运行的木桶计时器了!") return # 创建并存储任务 async def timer_task(): await asyncio.sleep(10) # 任务完成后从字典移除 del active_barrel_tasks[user_id] await ctx.send(f"{target_member.mention} 木桶快可以领取了!") task = asyncio.create_task(timer_task()) active_barrel_tasks[user_id] = task await ctx.send(f"为{target_member.mention}启动木桶计时器!") @client.command() async def barrelsc(ctx): user_id = ctx.author.id if user_id in active_barrel_tasks and not active_barrel_tasks[user_id].done(): task = active_barrel_tasks[user_id] task.cancel() del active_barrel_tasks[user_id] await ctx.send("木桶计时器已取消!") else: await ctx.send("没有可取消的木桶计时器!") # 运行机器人(替换成你的token) client.run("YOUR_BOT_TOKEN")
关键改进点
- 使用
active_barrel_tasks全局字典存储任务,跨命令共享状态 - 新增重复启动检查,避免同一用户同时运行多个计时器
- 任务完成后自动从字典移除,避免内存泄漏
- 取消任务时同步从字典删除条目,保证状态一致
额外说明
如果需要支持按频道而不是按用户管理计时器,只需要把字典的键换成ctx.channel.id即可,根据你的需求调整。
内容的提问来源于stack exchange,提问作者Clyde Owens
相关产品推荐
相关产品推荐

