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

discord.py如何在命令内部重启自身命令(无需重启机器人)

故障原因

代码存在两个核心问题导致逻辑不触发:

  • msg.content.lower是字符串的小写转换方法本身,你没有加()调用它,拿到的是方法对象,永远不可能和元组里的"y"/"yes"字符串匹配,判断恒为False,所以永远走else分支返回Bye。
  • Discord.py没有get_invoke这个内置方法,你拿不到正确的命令对象,就算前面的判断通过,这行代码也会抛出异常。
  • 你贴的代码还有缩进错误,函数内第一行await ctx.send没有和其他代码对齐,实际运行会直接抛缩进语法错误,属于粘贴时的排版问题。
实现方案

优先用循环实现,没有递归栈溢出风险,稳定性最高:

import asyncio # 计时要用到asyncio的sleep,不要漏导
from discord.ext import commands

# 对应你自己写的Cog类名
class PomodoroCog(commands.Cog):
    def __init__(self, client):
        self.client = client

    @commands.command(name='p_start')
    async def timer(self, ctx):
        while True:
            await ctx.send("Restart the pomodoro? Input y/yes to confirm, other input to exit.")
            msg = await self.client.wait_for(
                "message",
                check=lambda m: m.author == ctx.author and m.channel.id == ctx.channel.id
            )
            # 加()调用lower(),加strip()过滤用户不小心输入的前后空格
            if msg.content.strip().lower() in ("y", "yes"):
                await ctx.send("Pomodoro restarted, start timing...")
                # 在这里写番茄钟核心逻辑,比如25分钟工作+5分钟休息
                # 示例逻辑:
                await asyncio.sleep(25*60)
                await ctx.send("Work session finished, take a 5-minute break.")
                await asyncio.sleep(5*60)
                await ctx.send("Break finished.")
                # 核心逻辑跑完后会自动回到循环开头,再次询问是否重启
            else:
                await ctx.send("Bye!")
                break

如果你一定要用命令内部重入调用的方式,写法如下,注意这种方式如果用户反复重启次数过多,会触发Python递归深度限制报错,不推荐长期使用:

@commands.command(name='p_start')
async def timer(self, ctx):
    await ctx.send("Restart the pomodoro? Input y/yes to confirm, other input to exit.")
    msg = await self.client.wait_for(
        "message",
        check=lambda m: m.author == ctx.author and m.channel.id == ctx.channel.id
    )
    if msg.content.strip().lower() in ("y", "yes"):
        # 正确获取命令对象的API是get_command
        cmd = self.client.get_command('p_start')
        # 用上下文的invoke方法调用,会正常走命令的检查、错误处理逻辑
        await ctx.invoke(cmd)
    else:
        await ctx.send("Bye!")

补充提示:wait_for可以加timeout参数设置等待用户输入的超时时间,避免用户无响应时命令一直挂着占资源,比如await self.client.wait_for(..., timeout=60)就是等60秒没输入就抛TimeoutError,自行捕获处理即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 20:18:15