如何用循环更新数据库?Discord Bot任务循环报ctx参数缺失错误
问题解决与代码修复
错误原因
tasks.loop 装饰的定时任务函数不能接收ctx参数——这个任务是独立启动运行的,并非由用户命令触发,没有上下文对象(ctx)会被传入,所以会报缺少位置参数的错误。
修复后的完整代码
from discord.ext import tasks, commands import mysql.connector bot = commands.Bot(command_prefix="!", intents=commands.Intents.all()) @bot.event async def on_ready(): print(f"Logged in as: {bot.user.name}") # 启动定时任务,无需传参 if not check_xp_rank.is_running(): check_xp_rank.start() # 重命名任务函数避免和loop变量混淆,移除ctx参数 @tasks.loop(seconds=1) async def check_xp_rank(): # 遍历bot所在的所有服务器 for guild in bot.guilds: guild_id = guild.id table = f"PEOPLE_{guild_id}" connection = None cursor = None try: # 建立数据库连接 connection = mysql.connector.connect( host="localhost", port="3306", user="root", password="root", database="naruto_game" ) cursor = connection.cursor() # 修复SQL语句的空格问题:table和SET之间必须有空格 sql_update_query = f"UPDATE {table} SET rank = 'Elite Genin' WHERE xp >= 800" cursor.execute(sql_update_query) # 提交事务,否则修改不会生效 connection.commit() # 可选:打印更新的行数 print(f"服务器 {guild_id} 中更新了 {cursor.rowcount} 条记录") except mysql.connector.Error as error: print(f"服务器 {guild_id} 数据库操作失败: {error}") # 如果出错,回滚事务 if connection: connection.rollback() finally: # 关闭cursor和连接,避免资源泄漏 if cursor: cursor.close() if connection: connection.close() bot.run("你的Bot令牌")
关键修复点
- 移除任务函数的ctx参数:定时任务独立运行,无法获取命令上下文,改为遍历bot的所有服务器来处理每个服务器的数据库表
- 修复SQL语法错误:原语句中
table + "SET"会拼接成类似PEOPLE_123SET,缺少空格,改为{table} SET - 完善数据库资源管理:确保cursor和connection在finally块中关闭,避免资源泄漏;添加事务提交(必须commit才会保存修改)
- 优化XP判断逻辑:将
xp = 800改为xp >= 800,避免用户XP超过800后无法升级(如果你的需求是刚好800可以改回去) - 重命名任务函数:避免和
tasks.loop的loop名称混淆,提升代码可读性
额外注意事项
- 确保Bot的Intents已经开启服务器成员相关权限,否则
bot.guilds可能无法获取到服务器 - 每秒查询数据库可能会给数据库带来压力,建议根据实际需求调整间隔时间(比如改为10秒)
- 可以考虑添加日志系统,替代print语句,方便排查问题
内容的提问来源于stack exchange,提问作者TurkeySouls
相关产品推荐
相关产品推荐

