类型错误:元组索引必须是整数,而不是字符串。

78
我正在尝试从数据库中提取数据并将它们分配到不同的列表中。 这个特定的错误让我很困扰:“TypeError: tuple indices must be integers, not str” 我尝试将其转换为浮点数等,但没有成功。
代码如下:
conn=MySQLdb.connect(*details*)
cursor=conn.cursor()
ocs={}
oltv={}
query="select pool_number, average_credit_score as waocs, average_original_ltv as waoltv from *tablename* where as_of_date= *date*"
cursor.execute(query)
result=cursor.fetchall()

for row in result:
    print(row)
    ocs[row["pool_number"]]=int(row["waocs"])
    oltv[row["pool_number"]]=int(row["waoltv"])

打印语句的示例输出如下:

('MA3146', 711L, 81L)
('MA3147', 679L, 83L)
('MA3148', 668L, 86L)

这就是我得到的确切错误:

ocs[row["pool_number"]]=int(row["waocs"])
TypeError: tuple indices must be integers or slices, not str

我该如何解决这个错误?

10个回答

97

错误提示说了,row是一个元组,所以你不能使用row["pool_number"]。你需要使用索引:row[0]


今天Python 3报错:'tuple indices must be integers or slices, not str'。现在已经支持[start,stop,step]这样的切片表示法。更多信息请查看此答案 https://dev59.com/D3RB5IYBdhLWcg3wyqOo#509295 - Yan Pak

51

我认为你应该做

for index, row in result: 

如果您想通过名称进行访问。


11

TL;DR: 在你的 MySQLdb.connect 结尾处添加参数 cursorclass=MySQLdb.cursors.DictCursor


我有一段可用的代码,但是数据库被迁移了,我不得不更改主机 / 用户名 / 密码。这个更改后,我的代码停止工作并出现了这个错误。经过仔细检查,我复制粘贴连接字符串到一个多出一个指示的地方。旧代码如下:

 conn = MySQLdb.connect(host="oldhost",
                        user="olduser",
                        passwd="oldpass",
                        db="olddb", 
                        cursorclass=MySQLdb.cursors.DictCursor)

被替换为:

 conn = MySQLdb.connect(host="newhost",
                        user="newuser",
                        passwd="newpass",
                        db="newdb")

在结尾处添加参数cursorclass=MySQLdb.cursors.DictCursor可以让Python允许我使用列名作为索引来访问行。但不幸的是,复制粘贴时未能保留,导致出现错误。

因此,除了已提供的解决方案外,您还可以添加此参数,并以最初想要的方式访问行。 ^_^ 希望这能帮助其他人。


返回以下错误:AttributeError: 'module'对象没有属性'cursors' - Raptor
4
我正在使用PyMysql,这个方法对我有效。唯一需要更改的是将cursorclass=pymysql.cursors.DictCursor,之后我就可以使用列名了。谢谢! - Brad Ahrens

10

我知道这与问题本身并不特定,但是对于任何通过Google搜索进入的人:这个错误也可能是由于在创建元组时在对象后面加了逗号而不是字典造成的。

>>>dict = {}
>>>tuple = {},

元组

>>>tuple_ = {'key' : 'value'},
>>>type(tuple_)
<class 'tuple'>

字典

>>>dict_ = {'key' : 'value'} 
>>>type(dict_)        
<class 'dict'>

7

只需添加以下类似的参数即可解决我的问题。

cursor=conn.cursor(dictionary=True)

我希望这也会有所帮助。

你也可以使用Postgres来完成这个操作:https://www.psycopg.org/docs/extras.html - njh
这是针对旧版本的吗?对于sqlite3,获取以dict表示的行的方法是这个 - crimson_king

5
问题在于如何访问row。具体来说,是ocs[row["pool_number"]]=int(row["waocs"])中的row["waocs"]row["pool_number"]
如果您查阅fetchall()官方文档,您会发现:
“该方法获取查询结果集的所有(或所有剩余)行,并返回元组列表。”
因此,您必须使用row[__integer__]访问行的值,例如row[0]

1

虽然现在已经很晚了,但是可以通过在for语句中解包result元组来避免OP的问题,因为result正在迭代。假设result看起来像[('MA3146', 711L, 81L), ('MA3147', 679L, 83L), ('MA3148', 668L, 86L)],则解决方案如下。

result = [('MA3146', 711, 81), ('MA3147', 679, 83), ('MA3148', 668, 86)]
ocs, oltv = {}, {}
for pool_number, waocs, waoltv in result:
    ocs[pool_number] = int(waocs)
    oltv[pool_number] = int(waoltv)

通常情况下,如果您在标题中遇到了 TypeError(或更具体地说,TypeError:元组索引必须是整数或切片,而不是 str),请查看以下内容是否符合您的情况。
  1. 遍历字符串并尝试索引元组。您可能从未打算遍历字符串,它应该是返回整数的范围/列表等。

    tpl = tuple(range(10))
    for i in '10':
        tpl[i]           # <---- TypeError: tuple indices must be integers...
    
    
    for i in range(int('10')):
        tpl[i]           # <---- OK
    
  2. 在不解包的情况下遍历enumerate对象。枚举返回索引和项对的元组,可以直接解包为您遍历它时。

    lst = [{'a': 1}, {'a': 2}, {'a': 3}]
    for dct in enumerate(lst):
        dct['a']                       # TypeError
    
    
    for i, dct in enumerate(lst):
        dct['a']                       # OK
    
  3. 使用字符串索引命名元组。即使使用字符串定义了命名元组字段名称,也不能像字典键一样使用字符串索引命名元组。它可以使用整数索引或字段属性进行索引。

    from collections import namedtuple
    tpl = namedtuple('Tuple', 'x, y')(x=1, y=2)
    
    tpl['a']     # <---- TypeError
    tpl[0]       # <---- OK
    tpl.x        # <---- OK
    

0

欢迎。感谢您的贡献。请编辑以包含实现您建议的解决方案所需的确切代码。目前,这可能被视为(并且将作为)评论受到欢迎。当前状态下,它接近仅链接响应:不是完整的、自包含的解决方案,正如SO对答案所要求的那样。当您拥有足够的声望时,可以添加评论。包括参考链接以进行后续跟进和解释是高质量答案的标志,并倾向于随着用户学习适用于自己编码问题的内容而积累赞数。所以,非常好。(仅代码不鼓励) - SherylHohman
官方文档在这里:https://docs.python.org/3/library/sqlite3.html?highlight=sqlite#sqlite3-howto-row-factory - crimson_king

0

我看到你正在尝试通过行名进行识别。如果你想要在某一行中查找特定的列,可以使用[整数][列名]的方式。

例如,要遍历每一行并仅从具有“池编号”列标题的行中提取值,可以这样做:

for row in df_updated.iterrows():
    cell = row[1]['pool number']
    print(cell)

然后,代码将遍历每一行,但仅打印与“池号”列匹配的值


0
这个问题也曾让我困扰了一段时间。为了使sqlite游标返回每行的字典,以便您可以使用像row["waocs"]这样的东西,您需要指定row_factory。连接到数据库时,请设置连接的row_factory属性:
conn = sqlite3.connect('database.db')
conn.row_factory = sqlite3.Row

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接