【问题标题】:Don't understand cause of "IndexError: tuple index out of range" when formatting string格式化字符串时不理解“IndexError:元组索引超出范围”的原因
【发布时间】:2017-03-09 21:40:14
【问题描述】:

我查看了具有此IndexError 的类似问题,但没有找到对我的案例的解释。有人可以解释我为什么会收到错误消息吗?

以下代码

mySF2[0]=['000browser', '1', 'Floor', '0.92', '1.74', 'con', 'None']

insertfmt = ' '.join([
"INSERT INTO mySchema.myTable_{}_name (col1, col2, col3, col4, col5, col6)",  
"VALUES ({}, {}, NULLIF({},'None')::decimal, NULLIF({},'None')::decimal, {}, NULLIF({},'None')::int)"
         ])

insertfmt.format(mySF2[0])

给出这个错误

IndexError: tuple index out of range

但是,我计算了 7 个占位符(即大括号 {})和 7 个要输入的项目。那为什么会报错呢?

【问题讨论】:

  • '{}{}'.format([1,2]) 不起作用。您需要执行'{}{}'.format(*[1,2]) 来扩展[1,2]。这与'{}{}'.format(1,2) 相同
  • 同样使用字符串格式来构造查询本质上是不安全的——使用正确的 SQL 接口占位符函数(即单个 ? 字符并将元组作为额外参数传递给执行或执行许多方法。

标签: python string-formatting


【解决方案1】:

str.format() 接受可变数量的参数,这些参数对应于格式字符串中“孔”的数量。在您的情况下,您将单个参数(列表)传递给.format(),这会导致错误,因为它需要七个参数。

要将数组作为单独的参数传递给函数,您需要像这样使用* 运算符:

insertfmt.format(*mySF2[0])

【讨论】:

  • 谢谢,这个解释很清楚,更正效果很好。如果可以的话,我有一个后续问题。有没有办法指定一些参数(例如'Floor')应该保留字符串,即包括单引号?在当前形式中,所有参数都被去掉了引号,这阻碍了 SQL 语法。我查找了 .format 的文档,但没有找到解决方案:/
  • 直接回答您的问题:如果您绝对确定您的字符串不会包含任何特殊字符,例如转义单引号,您可以使用repr() 函数打印出 Python 表示的对象。例如。 repr('Floor') == "'Floor'"。但是,我想指出,像您这样将字符串插入表示 SQL 查询的格式字符串很容易受到 SQL 注入攻击。我强烈建议您使用可以安全地将参数转义到 SQL 语句中的库,以便恶意输入无法执行任意 SQL 语句。
  • 太棒了!非常感谢。我注意到你的警告,虽然现在它主要是供个人使用的,它应该没问题。更具体地说,我通过在需要的地方放置几个 {!r} 解决了这个问题。
  • 如何扩展字典而不是列表?
  • 要扩展字典,请使用** 而不是*
【解决方案2】:

在尝试使用 seaborn 和注释进行绘图时遇到了同样的问题。我正在使用

sns.heatmap(df, annot=True, fmt="{.0%}")

移除大括号修复它:

sns.heatmap(df, annot=True, fmt=".0%")

【讨论】:

    猜你喜欢
    • 2015-07-15
    • 1970-01-01
    • 2021-01-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多