【问题标题】:Python ---- TypeError: string indices must be integersPython ---- TypeError:字符串索引必须是整数
【发布时间】:2016-02-17 20:33:58
【问题描述】:

我有以下 Python 代码

from flask import Flask, jsonify, json

app = Flask(__name__)

with open('C:/test.json', encoding="latin-1") as f:
    dataset = json.loads(f.read())

@app.route('/api/PDL/<string:dataset_identifier>', methods=['GET'])
def get_task(dataset_identifier):
    global dataset
    dataset = [dataset for dataset in dataset if dataset['identifier'] == dataset_identifier]
    if len(task) == 0:
        abort(404)
    return jsonify({'dataset': dataset})

if __name__ == '__main__':
    app.run(debug=True)

Test.json 看起来像这样:

 {
    "dataset":  [{
                        "bureauCode":  [
                                           "016:00"
                                       ],
                        "description":  "XYZ",
                        "contactPoint":  {
                                             "fn":  "AG",
                                             "hasEmail":  "mailto:AG@AG.com"
                                         },
                        "distribution":  [
                                             {
                                                 "format":  "XLS",
                                                 "mediaType":  "application/vnd.ms-excel",
                                                 "downloadURL":  "https://www.example.com/xyz.xls"
                                             }
                                         ],
                        "programCode":  [
                                            "000:000"
                                        ],
                        "keyword":  [                                   "return to work",
                                    ],
                        "modified":  "2015-10-14",
                        "title":  "September 2015",
                        "publisher":  {
                                          "name":  "abc"
                                      },
                        "identifier":  US-XYZ-ABC-36,
                        "rights":  null,
                        "temporal":  null,
                        "describedBy":  null,
                        "accessLevel":  "public",
                        "spatial":  null,
                        "license":  "http://creativecommons.org/publicdomain/zero/1.0/",
                        "references":  [
                                           "http://www.example.com/example.html"
                                       ]
                    }
                ],
    "conformsTo":  "https://example.com"
}

当我像这样在 URL 中传递变量时:http://127.0.0.1:5000/api/PDL/1403 我收到以下错误:TypeError: string indices must be integers

知道“标识符”字段是一个字符串,并且我在 URL 中传递了以下内容:

http://127.0.0.1:5000/api/PDL/"US-XYZ-ABC-36"
http://127.0.0.1:5000/api/PDL/US-XYZ-ABC-36

我不断收到以下错误:

TypeError: string indices must be integers

知道我在这里缺少什么吗?我是 Python 新手!

【问题讨论】:

  • 不要在列表理解中使用与迭代器和列表相同的变量名
  • OP 不仅在列表 comp 中使用了两次该名称,而且他还将结果分配给了相同的名称。
  • @DanielRoseman:在 Py2 中,这也会大大减慢速度,因为 list comps 共享范围(因此所有 dataset 的使用都将共享全局,包括一遍又一遍地重新分配全局) ,让它变慢,而不仅仅是令人困惑。至少在 Py3 中,列表组合(如生成器表达式和 set/dict 组合)具有闭包范围,可以保护它们免受特定的低效率影响。
  • @RNar 你能澄清一下吗?
  • @ghadiehag:你把所有东西都命名为dataset;这充其量是令人困惑的,并且在最坏的情况下可能导致不正确的行为,因为dataset尽管有这个名字,但指的是(在不同的点上)由json.loads产生的dict,来自上述@的键的list 987654333@ 由列表推导生成,以及列表推导中迭代期间的键本身。

标签: python integer typeerror


【解决方案1】:

问题是您试图迭代字典而不是其中的数据源列表。因此,您正在遍历字典的键,它们是字符串。另外,正如上面提到的,如果您对列表和迭代器变量使用相同的名称,您将遇到问题。

这对我有用:

[ds for ds in dataset['dataset'] if ds['identifier'] == dataset_identifier]

【讨论】:

    【解决方案2】:

    您现在遇到的问题是,在列表理解的迭代过程中,第一次迭代将名称 dataset 从意味着 dictjson.loads-ed 更改为 dict 的键(@ 987654326@s 迭代他们的密钥)。因此,当您尝试使用 dataset['identifier']dataset 中查找值时,dataset 不再是 dict,而是您当前正在迭代的 str 键。

    停止重复使用相同的名称来表示不同的东西。

    从您发布的 JSON 中,您可能想要的是:

    with open('C:/test.json', encoding="latin-1") as f:
        alldata = json.loads(f.read())
    
    @app.route('/api/PDL/<string:dataset_identifier>', methods=['GET'])
    def get_task(dataset_identifier):
        # Gets the list of data objects from top level object
        # Could be inlined into list comprehension, replacing dataset with alldata['dataset']
        dataset = alldata['dataset']
        # data is a single object in that list, which should have an identifier key
        # data_for_id is the list of objects passing the filter
        data_for_id = [data for data in dataset if data['identifier'] == dataset_identifier]
        if len(task) == 0:
            abort(404)
        return jsonify({'dataset': data_for_id})
    

    【讨论】:

    • 注意:我没有使用global 关键字,因为如果名称不在本地范围内,从名称读取而不写入它自然会从全局变量中读取。如果我们像你一样使用global,并重写dataset,第一次使用后路由可能会失败,因为第一次使用会将全局重写为完全不同的类型。
    • 谢谢!这适用于我所有的 JSON 数据。我有 CSV 格式的数据,我还需要以 CSV 格式显示。对此有何意见?
    • @aghad:使用csv module。不要尝试手动解析/生成 CSV。
    • 这也能帮我在URL中传递参数?
    • 嗯,您需要预处理 CSV 以制作适合执行高效查找的某种数据结构。您通常不会将 CSV 作为 URL 参数传递(由于 URL 长度限制,将大量数据作为 URL 参数传递是有问题的),但生成它以供返回就可以了。
    猜你喜欢
    • 2016-03-26
    • 2023-03-03
    • 1970-01-01
    • 2022-11-02
    • 2019-04-26
    • 2020-08-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多