Почему я вижу "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
Это может произойти, если запятая отсутствует. Я столкнулся с ним, когда у меня был список из двух кортежей, каждый из которых состоял из строки в первой позиции и списка во второй. В одном случае я ошибочно пропустил запятую после первого компонента кортежа, и интерпретатор подумал, что я пытаюсь проиндексировать первый компонент.