
在使用 `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 错误。










