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

在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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 18:25:47