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


219

Я играю как с изучением 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"]])

Где "questions.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

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

Когда я настраиваю 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...

То, что вам не хватает, print repr(data)илиimport pprint; pprint.pprint(data)
Джон Мачин

Ответы:


116

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


159

Переменная itemявляется строкой. Индекс выглядит так:

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

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

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

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

42

dataэто dictобъект. Итак, переберите его так:

Python 2

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

Python 3

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

36

Ошибка типа для обозначения слайса str[a:b]

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


При работе со строками и обозначениями срезов ( обычная операция последовательности ) может случиться так, что a 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


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

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


1

У меня была похожая проблема с Pandas, вам нужно использовать функцию iterrows (), чтобы перебрать документацию Pandas для Pandas документации для iterrows

data = pd.read_csv('foo.csv')
for index,item in data.iterrows():
    print('{} {}'.format(item["gravatar_id"], item["position"]))

обратите внимание, что вам нужно обработать индекс в наборе данных, который также возвращается функцией.


0

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

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.