You need to enable JavaScript to run this app. discord.py 非Cog独立函数文件中wait_for为何无法捕获用户输入消息
优惠活动
大模型
产品
解决方案
定价
更多

discord.py 非Cog独立函数文件中wait_for为何无法捕获用户输入消息

故障根源定位
  • 引用断裂:anime.py 内调用 bot.wait_for 时,当前文件作用域内无对应bot实例定义,也未从主入口导入,运行至该行直接触发NameError,无法进入等待消息流程。此前尝试替换为self.bot或client无效,是因为业务逻辑是独立异步函数,无类实例上下文,不存在self绑定对象。
  • 配置缺失:原wait_for调用未配置过滤规则与超时参数。即便bot引用修正,默认逻辑会捕获全频道、全用户的消息,甚至机器人自身发送的列表提示也会被判定为用户回应;未传入timeout参数时,代码中编写的asyncio.TimeoutError捕获分支永远不会触发,程序会陷入无限等待。
  • 风险隐患:跨文件反向导入bot实例极易引发循环导入(主入口导入业务模块、业务模块反向导入主入口的bot对象),导致程序启动直接崩溃。
落地修改方案

采用参数传值替代跨文件反向导入,同时补充wait_for的必要配置,从根源解决消息捕获问题:

  • 调整函数传参链路:主入口调用业务函数时,直接将自身初始化的bot实例作为参数传入,避免跨文件导入的循环依赖问题。
  • 补充wait_for的过滤规则:仅接收与原命令同频道、由触发命令的同一用户发送的非机器人消息,过滤无效输入。
  • 补充超时配置:设置60秒等待阈值,触发原代码中编写的超时取消逻辑。

修改后代码

主入口文件 main.py

import discord
import asyncio
from discord.ext import commands
from anime import search_anime

bot = commands.Bot(command_prefix="m.")
TOKEN = "INSERT TOKEN HERE"

@bot.event
async def on_ready():
    print("Connected to discord")

@bot.command(name="searchanime", help="Searches through the MAL Database to find an anime. Requires a title to search")
async def search(ctx, *, query):
    # 调用业务函数时传入当前bot实例
    await search_anime(ctx, query, bot)

bot.run(TOKEN)

业务逻辑文件 anime.py

import discord
import requests
import asyncio

headers = {
    'x-rapidapi-key': "2ed26cb89emsh2b7cb079ec42fd9p15290cjsne485ef05078a",
    'x-rapidapi-host': "jikan1.p.rapidapi.com"
}

# 形参新增bot字段,接收主入口传入的机器人实例
async def search_anime(ctx, query, bot):
    url = "https://jikan1.p.rapidapi.com/search/anime"
    querystring = {"q": query, "format": "json"}
    response = requests.request("GET", url, headers=headers, params=querystring).json()

    response_list = []
    for i in range(4):
        response_list.append(response["results"][i])

    await ctx.send("Message 'm.(desired number)' without the parenthesis to select the anime you are looking for from this list")
    for i in range(len(response_list)):
        await ctx.send(f"{i+1}) {response_list[i]['title']}")
    
    # 定义消息校验规则
    def check(message):
        return (
            message.channel == ctx.channel 
            and message.author == ctx.author 
            and not message.author.bot
        )

    try:
        # 传入校验规则与60秒超时阈值
        msg = await bot.wait_for("message", check=check, timeout=60.0)
        await ctx.send(msg.content)
    except asyncio.TimeoutError:
        await ctx.send("Cancelling due to timeout")

补充提示:原代码中使用的同步requests库会阻塞Discord的异步事件循环,生产环境建议替换为异步HTTP客户端如aiohttp,避免程序卡顿。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.26 05:15:10