Почему я вижу "TypeError: строковые индексы должны быть целыми"?

Я играю и с изучением python, и с попыткой получить проблемы github в удобочитаемой форме. Использование совета Как конвертировать JSON в CSV? Я придумал следующее:

import json
import csv

f=open('issues.json')
data = json.load(f)
f.close()

f=open("issues.csv","wb+")
csv_file=csv.writer(f)

csv_file.writerow(["gravatar_id","position","number","votes","created_at","comments","body","title","updated_at","html_url","user","labels","state"])

for item in data:
        csv_file.writerow([item["gravatar_id"], item["position"], item["number"], item["votes"], item["created_at"], item["comments"], item["body"], item["title"], item["updated_at"], item["html_url"], item["user"], item["labels"], item["state"]])

Где "issues.json" - это json файл, содержащий мои проблемы github. Когда я пытаюсь запустить это, я получаю

File "foo.py", line 14, in <module>
csv_file.writerow([item["gravatar_id"], item["position"], item["number"], item["votes"], item["created_at"], item["comments"], item["body"], item["title"], item["updated_at"], item["html_url"], item["user"], item["labels"], item["state"]])

TypeError: string indices must be integers

Что мне здесь не хватает? Каковы "строковые индексы"? Я уверен, что как только я получу эту работу, у меня будет больше проблем, но пока я просто люблю работать!

UPDATE: Когда я настраиваю оператор for просто

for item in data:
    print item

что я получаю... "проблемы" - так что я делаю что-то более сложное. Вот немного моего json:

{"issues":[{"gravatar_id":"44230311a3dcd684b6c5f81bf2ec9f60","position":2.0,"number":263,"votes":0,"created_at":"2010/09/17 16:06:50 -0700","comments":11,"body":"Add missing paging (Older>>) links...

когда я печатаю data, похоже, что он очень странно выглядит:

{u'issues': [{u'body': u'Add missing paging (Older>>) lin...

Ответ 1

item скорее всего, строка в вашем коде; индексы строк - это квадратные скобки, например, gravatar_id. Поэтому я сначала проверил вашу переменную data, чтобы увидеть, что вы там получили; Я думаю, что data - это список строк (или, по крайней мере, список, содержащий хотя бы одну строку), в то время как это должен быть список словарей.

Ответ 2

Переменная item - это строка. Индекс выглядит следующим образом:

>>> mystring = 'helloworld'
>>> print mystring[0]
'h'

В приведенном выше примере используется индекс 0 строки для обращения к первому символу.

Строки не могут содержать строковые индексы (например, словари). Так что это не сработает:

>>> mystring = 'helloworld'
>>> print mystring['stringindex']
TypeError: string indices must be integers

Ответ 3

data является объектом dict. Итак, перебирайте его так:

Python 2

for key, value in data.iteritems():
    print key, value

Python 3

for key, value in data.items():
    print(key, value)

Ответ 4

Ошибка типа для обозначения фрагмента str[a:b]

tl;dr: используйте двоеточие : вместо запятой между двумя индексами a и b в str[a:b]


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

Пример

>>> my_string = "hello world"
>>> my_string[0,5]
TypeError: string indices must be integers

Мы явно передали два целых числа для индексов в обозначение среза, верно? Так в чем здесь проблема?

Эта ошибка может быть очень неприятной - особенно в начале изучения Python - потому что сообщение об ошибке немного вводит в заблуждение.

Объяснение

Мы неявно передали кортеж из двух целых чисел (0 и 5) в нотацию среза, когда мы вызвали my_string[0,5], потому что 0,5 (даже без скобок) оценивает тот же кортеж, что и (0,5).

Запятой , на самом деле достаточно, чтобы Python оценил что-то как кортеж:

>>> my_variable = 0,
>>> type(my_variable)
<class 'tuple'>

Итак, что мы там сделали, на этот раз явно:

>>> my_string = "hello world"
>>> my_tuple = 0, 5
>>> my_string[my_tuple]
TypeError: string indices must be integers

Теперь, по крайней мере, сообщение об ошибке имеет смысл.

Решение

Нам нужно заменить запятую , на двоеточие :, чтобы правильно разделить два целых числа:

>>> my_string = "hello world"
>>> my_string[0:5]
'hello'

Более понятное и полезное сообщение об ошибке могло выглядеть примерно так:

TypeError: string indices must be integers (not tuple)

Хорошее сообщение об ошибке показывает пользователю, что он сделал неправильно, и было бы более очевидно, как решить проблему.

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

Извлеченные уроки

  • нотация среза использует двоеточия : для разделения своих индексов (и диапазона шагов, например str[from:to:step])
  • кортежи определяются запятыми , (например, t = 1,)
  • добавить некоторую информацию в сообщения об ошибках, чтобы пользователи поняли, что пошло не так

Приветствия и счастливое программирование
winklerrr


[Я знаю, что на этот вопрос уже был дан ответ, и это был не совсем тот вопрос, который задал автор темы, но я пришел сюда из-за вышеуказанной проблемы, которая приводит к тому же сообщению об ошибке. По крайней мере, мне понадобилось некоторое время, чтобы найти эту маленькую опечатку.

Поэтому я надеюсь, что это поможет кому-то еще, кто наткнулся на ту же ошибку, и сэкономит им время на обнаружение этой крошечной ошибки.]

Ответ 5

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