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

Discord.py Cogs中client.wait_for报错:非异步上下文无法访问loop属性

Discord.py Cog中使用wait_for报错"loop attribute cannot be accessed in non-async contexts"

问题根源

你遇到的错误核心有两个原因:

  • Cog中错误使用全局client变量调用wait_for:Cog作为机器人的扩展模块,必须通过类实例的self.bot属性访问机器人对象,全局client在Cog上下文里无法正确关联事件循环。
  • 代码存在拼写错误:client.await_for是错误写法,正确方法名为wait_for。

解决方案步骤

  1. 确保Cog类正确继承commands.Cog,并在初始化方法中接收bot参数绑定到self.bot
  2. 将所有client.wait_for及错误的client.await_for替换为self.bot.wait_for
  3. 提取重复代码逻辑(如消息检查、猜数字循环),减少冗余并提升可维护性

修正后的完整代码

import re
import random
from discord.ext import commands

class GuessCog(commands.Cog):
    def __init__(self, bot):
        self.bot = bot

    # 提取重复的消息检查逻辑
    def _guess_check(self, ctx, msg):
        return msg.author == ctx.author and msg.channel == ctx.channel

    # 提取重复的猜数字循环逻辑
    async def _run_guess_loop(self, ctx, range_min, range_max, attempts):
        await ctx.send(
            f"Now guess a number between **{range_min}-{range_max}**, you have **{attempts}** attempts. Type 'stop' to give up."
        )
        entry_count = 0
        target_num = random.randrange(range_min, range_max + 1)  # 修正randrange,确保包含最大值
        
        while entry_count < attempts:
            msg = await self.bot.wait_for('message', check=lambda m: self._guess_check(ctx, m))
            entry_count += 1
            
            if msg.content.lower() == "stop":
                await ctx.send(f"You gave up 😢")
                await ctx.send(f"The number was **{target_num}**")
                return
            
            # 处理非数字输入
            try:
                user_guess = int(msg.content)
            except ValueError:
                await ctx.send(f"Please enter a valid number!")
                entry_count -= 1
                continue
            
            if user_guess < range_min or user_guess > range_max:
                await ctx.send(f"Pick a number between **{range_min}-{range_max}**!")
                entry_count -= 1
            elif user_guess == target_num:
                await ctx.send(f"**Good job, it was {target_num}!**")
                return
            else:
                await ctx.send(f"Nope, keep guessing", delete_after=2)
        
        # 用完所有尝试次数
        await ctx.send(f"You ran out of inputs, it was **{target_num}**!")

    @commands.command()
    async def guess(self, ctx):
        try:
            await ctx.send(
                f"Pick a range of numbers you want and the number of attempts you want."
                f"Ex: '__**1-10**, **4**__' or '__**600-10**, **200**__'"
            )
            # 等待用户输入范围和尝试次数
            msg = await self.bot.wait_for('message', check=lambda m: self._guess_check(ctx, m))
            num_list = re.findall(r'\d+', msg.content)
            
            # 验证输入格式
            if len(num_list) != 3:
                await ctx.send("Invalid input! Please follow the format: 'min-max, attempts'")
                return
            
            range_1 = int(num_list[0])
            range_2 = int(num_list[1])
            attempts = int(num_list[2])
            
            # 自动调整范围顺序
            if range_1 > range_2:
                range_1, range_2 = range_2, range_1
            
            # 启动猜数字循环
            await self._run_guess_loop(ctx, range_1, range_2, attempts)
        except Exception as error:
            print(f"{error}")
            await ctx.send(f"Problem: **[{error}]**")

# 注册Cog的标准函数(适配discord.py v2.x)
async def setup(bot):
    await bot.add_cog(GuessCog(bot))

额外优化说明

  • 新增输入验证逻辑,避免用户错误输入导致程序崩溃
  • 提取重复代码模块,提升代码可读性和可维护性
  • 修正random.randrange参数,确保能取到范围最大值
  • 使用setup函数注册Cog,符合discord.py最新版本规范

内容的提问来源于stack exchange,提问作者Proxima

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 01:20:23