2015-11-16 7 views
2

У меня есть ниже код PythonPython ---- TypeError: строковые индексы должны быть целыми

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:[email protected]" 
             }, 
         "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!

+2

не использовать то же имя переменной, как ваш итератор и список в список вашего понимания –

+1

Не только OP используется имя дважды в списке компе, но он также назначен результат с тем же именем. –

+0

@ DanielRoseman: И в Py2 это также замедлит работу, потому что список comps разделяет область (так что все использование 'dataset' будет делить глобальное, включая переназначение глобального снова и снова), что замедляет работу, а не только сбивает с толку. По крайней мере, в Py3 список comps (например, выражений генератора и set/dict comps) имеет закрытие, которое защитит их от этой неэффективности. – ShadowRanger

ответ

1

Проблема у вас есть прямо сейчас, что во время итерации в списке понимание, очень первая итерация меняет название dataset от означая dict вы json.loads -ed к ключу что dict (dict с перебирать ключи). Поэтому, когда вы пытаетесь найти значение в dataset с dataset['identifier'], 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}) 
+1

Примечание: я не использовал ключевое слово 'global', потому что чтение из имени без записи на него естественно читается из глобальных переменных, если имя не находится в локальной области. И если бы мы использовали «глобальный», как вы, и переписали «набор данных», маршрут мог потерпеть неудачу после первого использования, потому что первое использование переписало бы глобальный тип совершенно другого типа. – ShadowRanger

+0

Спасибо! Это работает со всеми моими данными JSON. У меня есть данные в CSV, которые мне также нужно отображать в CSV. Любой ввод? – aghad

+0

@aghad: Используйте модуль '' csv' '(https://docs.python.org/3/library/csv.html). Не пытайтесь разбирать/создавать CSV вручную. – ShadowRanger

2

Проблема в том, что вы пытаетесь итерацию словарь вместо списка источников данных внутри него. Как следствие, вы повторяете ключи словаря, которые являются строками. Кроме того, как уже упоминалось выше, у вас будут проблемы, если вы используете одно и то же имя для списка и переменной итератора.

Это работает для меня:

[ds for ds in dataset['dataset'] if ds['identifier'] == dataset_identifier] 
Смежные вопросы