Discord.py 问题:答案逐步展示期间无法接收用户回答
Discord机器人问题:答案展示期间无法接收用户回答
我开发了一个简易Discord机器人,做了个功能:每隔2秒逐个字母展示答案,但现在有个问题——在答案完全展示完之前,机器人没法接收用户的回答。
完整代码
await ctx.send(a) # 发送问题 respuestas = b # 答案列表 # 逐个展示字母 string = respuestas[0] blanked_string = [x if x.isspace() else "-" for x in string] nonspace_indexes = [i for i, _ in enumerate(string)] random.shuffle(nonspace_indexes) for i in nonspace_indexes: blanked_string[i] = string[i] await ctx.send(''.join(blanked_string)) await asyncio.sleep(2) # 检查用户回答 def check(msg=discord.Message) -> True: return msg.content.lower() in respuestas and msg.channel == ctx.message.channel try: guess = await bot.wait_for('message', timeout=6, check=check) return await ctx.send(f"{guess.author.mention} 第一个答对!") except asyncio.TimeoutError: await ctx.send("时间到!")
问题原因
当前代码是同步执行的:先把整个字母展示循环跑完(每个步骤都等待2秒),才会执行bot.wait_for('message')开始监听用户输入。这就导致展示过程中用户发送的消息完全不会被机器人处理。
解决方案
用asyncio.create_task把字母展示逻辑做成异步任务,让它和用户输入监听逻辑并行运行,这样机器人在展示字母的同时,也能实时接收用户回答。
修改后的代码
import asyncio import discord import random async def your_command(ctx, bot): await ctx.send(a) # 发送问题 respuestas = b # 答案列表 string = respuestas[0] blanked_string = [x if x.isspace() else "-" for x in string] nonspace_indexes = [i for i, _ in enumerate(string)] random.shuffle(nonspace_indexes) # 封装字母展示的异步函数 async def reveal_letters(): for i in nonspace_indexes: blanked_string[i] = string[i] await ctx.send(''.join(blanked_string)) await asyncio.sleep(2) await ctx.send("字母展示完毕,最后6秒答题时间!") # 检查用户回答的函数,排除机器人自身消息 def check(msg): return (msg.content.lower() in respuestas and msg.channel == ctx.message.channel and msg.author != bot.user) # 启动后台展示任务 reveal_task = asyncio.create_task(reveal_letters()) try: # 超时时间设为展示总时长 + 额外答题时间 total_timeout = 2 * len(nonspace_indexes) + 6 guess = await bot.wait_for('message', timeout=total_timeout, check=check) # 用户答对后立即终止展示任务 reveal_task.cancel() await ctx.send(f"{guess.author.mention} 第一个答对!") except asyncio.TimeoutError: # 超时后终止未完成的展示任务 if not reveal_task.done(): reveal_task.cancel() await ctx.send("时间到!") finally: # 处理任务取消的异常,避免控制台报错 try: await reveal_task except asyncio.CancelledError: pass
关键修改说明
- 异步任务并行:用
asyncio.create_task启动字母展示任务,让它在后台独立运行,不阻塞用户输入监听 - 超时时间调整:把
wait_for的超时时间设为展示总时长(2秒×字母数量)加上额外答题时间,覆盖整个交互流程 - 任务终止逻辑:用户答对或超时后,主动取消展示任务,避免机器人继续发送多余的字母消息
- 排除自身消息:检查函数中新增
msg.author != bot.user,防止机器人把自己发送的展示消息误判为用户回答
内容的提问来源于stack exchange,提问作者jean
相关产品推荐
相关产品推荐

