Чому я бачу "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"]])

Де "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

Що я тут пропускаю? Що таке "рядкові індекси"? Я впевнений, що як тільки я дію до цього, у мене виникне більше проблем, але поки що я просто хотів би, щоб це працювало!

Коли я налаштовую 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це список рядків (або, принаймні, список, що містить принаймні один рядок), тоді як він повинен бути списком словників.


158

Змінна item- рядок. Індекс виглядає приблизно так:

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

У наведеному вище прикладі використовується 0індекс рядка для позначення першого символу.

У рядках не може бути строкових індексів (як, наприклад, словники). Отже, це не спрацює:

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

42

dataє dictоб’єктом. Отже, повторіть це так:

Пітон 2

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

Пітон 3

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

36

TypeError для позначення фрагментів 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


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

Тож я сподіваюся, що це допоможе комусь, хто натрапив на ту ж помилку, і заощадить їм деякий час, знайшовши цю крихітну помилку.]


0

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


0

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

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

зауважте, що вам потрібно обробляти індекс у наборі даних, який також повертається функцією.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.