报错TypeError: tuple indices must be integers or slices, not str,求排查代码问题
搞定
TypeError: tuple indices must be integers or slices, not str 报错 嘿,我一眼就看出问题出在哪了——你遇到的这个类型错误,根源是数据库游标返回的是元组(tuple),但你却想用字符串键"count"去索引它,元组只能用整数索引或者切片,所以才会报错。
为啥会这样?
默认情况下,Python里大多数数据库驱动(比如sqlite3、MySQLdb)的游标,执行fetchone()后返回的都是元组格式,比如你查COUNT(*)得到的结果会是(50,)这样的元组,而不是像字典那样可以用"count"来取值的结构。你写的result["count"]相当于用字符串去“定位”元组的元素,这显然不符合元组的访问规则,自然触发错误。
两种简单解决方案:
方案1:直接用整数索引取结果
既然返回的是元组,直接用索引[0]获取第一个元素就行,毕竟你的SQL语句SELECT COUNT(*) as count只会返回一个数值:
@checks.can_embed() @commands.command(name="botinfo") async def botinfo(self, ctx: UKGCtx): """Shows advanced information about the bot.""" char_count = 0 deaths_count = 0 levels_count = 0 with closing(userDatabase.cursor()) as c: c.execute("SELECT COUNT(*) as count FROM chars") result = c.fetchone() if result is not None: char_count = result[0] # 换成整数索引,直接取第一个元素 c.execute("SELECT COUNT(*) as count FROM char_deaths") result = c.fetchone() if result is not None: deaths_count = result[0] c.execute("SELECT COUNT(*) as count FROM char_levelups") result = c.fetchone() if result is not None: levels_count = result[0]
方案2:让游标返回字典(更符合你的写法习惯)
如果你还是想用result["count"]这种字段名的方式访问结果,可以修改游标类型,让它返回字典。不同数据库驱动的设置方式略有不同:
- 用
sqlite3的话,设置cursorclass=sqlite3.Row; - 用
MySQLdb的话,初始化游标时用cursor(MySQLdb.cursors.DictCursor); - 其他数据库驱动基本都有类似的“字典游标”选项。
拿sqlite3举例子,修改后的代码是这样:
@checks.can_embed() @commands.command(name="botinfo") async def botinfo(self, ctx: UKGCtx): """Shows advanced information about the bot.""" char_count = 0 deaths_count = 0 levels_count = 0 # 创建能返回字典的游标 with closing(userDatabase.cursor(cursorclass=sqlite3.Row)) as c: c.execute("SELECT COUNT(*) as count FROM chars") result = c.fetchone() if result is not None: char_count = result["count"] # 现在可以正常用字符串键访问了 c.execute("SELECT COUNT(*) as count FROM char_deaths") result = c.fetchone() if result is not None: deaths_count = result["count"] c.execute("SELECT COUNT(*) as count FROM char_levelups") result = c.fetchone() if result is not None: levels_count = result["count"]
额外提个小优化
你这段代码里重复的查询逻辑挺多的,可以封装成一个小函数,减少冗余,维护起来也更方便:
def get_table_count(cursor, table_name): cursor.execute(f"SELECT COUNT(*) FROM {table_name}") result = cursor.fetchone() return result[0] if result else 0 # 然后在botinfo里调用就行: with closing(userDatabase.cursor()) as c: char_count = get_table_count(c, "chars") deaths_count = get_table_count(c, "char_deaths") levels_count = get_table_count(c, "char_levelups")
这样代码清爽多了对吧?
内容的提问来源于stack exchange,提问作者James
相关产品推荐
相关产品推荐

