在discord.py Cogs中使用wait_for导致代码阻塞的问题咨询
问题描述
我正在开发一款Discord机器人,它会随机发送“重组句子”问题供用户作答。但使用wait_for等待用户响应时,发现代码完全阻塞(断点调试确认了这个情况),不清楚原因,也对在Cog中正确使用该方法有困惑。以下是我的Cog代码(不含导入语句):
class firework_economy(commands.Cog): def __init__(self, bot): self.bot = bot @commands.Cog.listener() async def on_message(self, message): if message.author.bot: return else: rand_num = randint(1, 10) print(rand_num) if rand_num == 5: ss = open('scrambled sentences.txt','r') sslist = ss.readlines() chosen_sentence = choice(sslist) await message.reply(f"Unscramble the following sentence for a chance to win a firework:\n\n`{chosen_sentence}`") def check(m): return m.content == 'answer' and m.channel == message.channel msg = await commands.Bot().wait_for("message") await message.channel.send(f"{msg.author.mention} was first!") async def setup(bot): await bot.add_cog(firework_economy(bot))
问题分析与修复方案
1. wait_for阻塞的核心原因
你创建了一个全新的commands.Bot()实例调用wait_for,而非使用Cog中已经初始化并连接到Discord网关的self.bot。这个新实例没有监听任何消息事件,自然永远收不到触发信号,导致代码永久阻塞。
2. 其他需修复的问题
- 未启用自定义校验逻辑:你定义了
check函数但未传入wait_for,导致任何消息都会触发响应,不符合需求。 - 文件资源泄漏:直接用
open()打开文件后未关闭,建议用with语句自动管理资源。 - 命令冲突:
on_message监听器会阻止其他commands.Command执行,需添加process_commands调用。
修复后的完整代码
import random from random import randint, choice import discord from discord.ext import commands import asyncio class firework_economy(commands.Cog): def __init__(self, bot): self.bot = bot @commands.Cog.listener() async def on_message(self, message): if message.author.bot: return rand_num = randint(1, 10) print(rand_num) if rand_num == 5: # 自动关闭文件的写法 with open('scrambled sentences.txt','r') as ss: sslist = ss.readlines() chosen_sentence = choice(sslist).strip() # 去除换行符 await message.reply(f"Unscramble the following sentence for a chance to win a firework:\n\n`{chosen_sentence}`") def check(m): # 校验:同频道、非机器人、内容匹配正确答案 return m.channel == message.channel and not m.author.bot and m.content == 'answer' # 使用Bot实例调用wait_for,添加超时避免永久阻塞 try: msg = await self.bot.wait_for("message", check=check, timeout=60.0) await message.channel.send(f"{msg.author.mention} was first!") except asyncio.TimeoutError: await message.channel.send("时间到!没人答对。") # 处理其他命令,防止监听器拦截 await self.bot.process_commands(message) async def setup(bot): await bot.add_cog(firework_economy(bot))
关键修复点说明
- 替换
commands.Bot().wait_for()为self.bot.wait_for(),确保使用已连接的Bot实例监听事件。 - 传入
check参数,精准过滤符合条件的用户消息。 - 添加
timeout参数和异常捕获,避免无人响应时永久阻塞。 - 用
with语句处理文件,自动释放资源。 - 添加
await self.bot.process_commands(message),保证其他命令正常执行。
内容的提问来源于stack exchange,提问作者DRags
相关产品推荐
相关产品推荐

