Discord.py 中 @tasks.loop 启动失败的常见原因及修复方案

在使用 `discord.py` 的 `@tasks.loop` 时,若 cog 初始化后任务未正确启动,常因 `bot.add_cog()` 未被 `await` 调用导致 `typeerror: object nonetype can't be used in 'await' expression` —— 根本原因是 `add_cog()` 自 v2.0 起已是异步方法,必须显式 `await`。

该错误通常出现在将含 @tasks.loop 的 Cog 作为扩展(extension)加载时。你的 loop.py 文件中定义了 setup() 函数,但旧写法 bot.add_cog(loop(bot)) 在 discord.py v2.0+ 中会返回一个协程对象(而非直接执行),而你未 await 它,导致协程被丢弃,进而引发运行时警告和后续 NoneType 错误。

✅ 正确做法是:将 setup 函数声明为 async,并 await bot.add_cog(...):

# loop.py(修正后)
from discord.ext import commands, tasks
from datetime import time

class LoopCog(commands.Cog):  # 建议使用 PascalCase 类名
    def __init__(self, bot):
        self.bot = bot
        self.check.start()  # ✅ 任务在实例化时立即启动

    @tasks.loop(time=time(11, 40))  # 每天 11:40 执行
    async def check(self):
        print(f"[{datetime.now().strftime('%H:%M:%S')}] Running scheduled task...")
        # ✅ 此处添加你的业务逻辑,例如发送消息、检查状态等
        # 注意:若需访问频道/用户,请确保 bot 已就绪且权限充足

    @check.before_loop
    async def before_check(self):
        await self.bot.wait_until_ready()  # ⚠️ 关键!避免在 bot 就绪前执行任务

def setup(bot):
    # ✅ 必须是 async + await(discord.py v2.0+ 强制要求)
    return bot.add_cog(LoopCog(bot))

⚠️ 重要说明:

  • setup() 函数必须返回 bot.add_cog(...) 协程(不能 await 后返回 None),因为 load_extension() 内部会自动 await 它;
  • 若你手动 await bot.add_cog(...),会导致 RuntimeWarning: coroutine was never awaited —— 因为 load_extension() 会再次尝试 await 一个 None;
  • 因此标准写法是:setup 为普通函数,直接返回协程对象(不加 await),由框架负责调度;
  • 同时务必添加 @check.before_loop 钩子并调用 bot.wait_until_ready(),否则 check() 可能在 on_ready 前触发,导致 self.bot.user 等属性为 None。

? 补充建议:

  • 在 bot.py 中,推荐使用 async def setup_hook(self) 替代 on_ready 来加载扩展(更符合 v2.0+ 最佳实践):

    class MyBot(commands.Bot):
        def __init__(self):
            super().__init__(command_prefix='.', intents=discord.Intents.all())
    
        async def setup_hook(self):
            await self.load_extension("loop")
            print("loop extension loaded.")
    
        async def on_ready(self):
            print(f

    '{self.user} is now running!')
  • 检查 loop.py 是否位于 bot.py 同级目录,且文件名不含非法字符(如开头数字、空格);

  • 运行前确认已安装兼容版本:pip install -U discord.py(推荐 ≥ 2.3.2)。

遵循以上修正,@tasks.loop 将稳定启动,不再出现 NoneType await 错误。