Tại sao tôi lại thấy Kiểu TypeError: các chỉ số chuỗi phải là số nguyên?


219

Tôi đang chơi với cả việc học python và cố gắng đưa các vấn đề về github thành một dạng có thể đọc được. Sử dụng lời khuyên về Làm cách nào tôi có thể chuyển đổi JSON sang CSV? Tôi nghĩ ra cái này:

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"]])

Trong đó "problems.json" là tệp json chứa các vấn đề github của tôi. Khi tôi cố chạy nó, tôi nhận được

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

Tôi đang thiếu gì ở đây? Đó là "chỉ số chuỗi"? Tôi chắc chắn rằng một khi tôi làm việc này tôi sẽ có nhiều vấn đề hơn, nhưng bây giờ, tôi chỉ thích làm việc này!

Khi tôi điều chỉnh forcâu lệnh thành đơn giản

for item in data:
    print item

những gì tôi nhận được là ... "các vấn đề" - vì vậy tôi đang làm điều gì đó sai cơ bản hơn. Đây là một chút json của tôi:

{"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...

Khi tôi in, datacó vẻ như nó đang bị mung rất kỳ quặc:

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

Những gì bạn đang thiếu là print repr(data)hoặcimport pprint; pprint.pprint(data)
John Machin

Câu trả lời:


116

itemrất có thể là một chuỗi trong mã của bạn; các chỉ số chuỗi là những cái trong ngoặc vuông, vd gravatar_id. Vì vậy, trước tiên tôi sẽ kiểm tra databiến của bạn để xem những gì bạn nhận được ở đó; Tôi đoán đó datalà một danh sách các chuỗi (hoặc ít nhất là một danh sách chứa ít nhất một chuỗi) trong khi nó phải là một danh sách các từ điển.


158

Biến itemlà một chuỗi. Một chỉ mục trông như thế này:

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

Ví dụ trên sử dụng 0chỉ mục của chuỗi để chỉ ký tự đầu tiên.

Chuỗi không thể có chỉ số chuỗi (như từ điển có thể). Vì vậy, điều này sẽ không hoạt động:

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

42

datalà một dictđối tượng. Vì vậy, lặp đi lặp lại trên nó như thế này:

Con trăn 2

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

Con trăn 3

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

36

LoạiError cho ký hiệu lát str[a:b]

tl; dr: sử dụng dấu hai chấm : thay vì dấu phẩy ở giữa hai chỉ số abtrongstr[a:b]


Khi làm việc với các chuỗiký hiệu lát (một thao tác chuỗi phổ biến ), có thể xảy ra rằng a TypeErrorđược nâng lên, chỉ ra rằng các chỉ số phải là số nguyên, ngay cả khi chúng rõ ràng là.

Thí dụ

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

Chúng tôi rõ ràng đã chuyển hai số nguyên cho các chỉ số cho ký hiệu lát, phải không? Vậy vấn đề ở đây là gì?

Lỗi này có thể rất bực bội - đặc biệt là khi bắt đầu học Python - vì thông báo lỗi hơi sai lệch.

Giải trình

Chúng tôi ngầm chuyển một bộ gồm hai số nguyên (0 và 5) cho ký hiệu lát khi chúng tôi gọi my_string[0,5]bởi vì 0,5(ngay cả khi không có dấu ngoặc đơn) ước tính cho cùng một bộ dữ liệu như (0,5)sẽ làm.

Dấu phẩy ,thực sự đủ để Python đánh giá một cái gì đó như một tuple:

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

Vì vậy, những gì chúng tôi đã làm ở đó, lần này rõ ràng:

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

Bây giờ, ít nhất, thông báo lỗi có ý nghĩa.

Giải pháp

Chúng ta cần phải thay thế các dấu phẩy , với một thư đại tràng : để tách hai số nguyên một cách chính xác:

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

Một thông báo lỗi rõ ràng và hữu ích hơn có thể là một cái gì đó như:

TypeError: string indices must be integers (not tuple)

Một thông báo lỗi tốt cho người dùng thấy trực tiếp những gì họ đã làm sai và rõ ràng hơn là làm thế nào để giải quyết vấn đề.

[Vì vậy, lần tới khi bạn thấy mình chịu trách nhiệm viết thông báo mô tả lỗi, hãy nghĩ đến ví dụ này và thêm lý do hoặc thông tin hữu ích khác vào thông báo lỗi để cho bạn và có thể người khác hiểu được vấn đề đã xảy ra.]

Bài học kinh nghiệm

  • ký hiệu lát sử dụng dấu hai chấm :để phân tách các chỉ số của nó (và phạm vi bước, ví dụ str[from:to:step])
  • bộ dữ liệu được xác định bởi dấu phẩy ,(ví dụ t = 1,)
  • thêm một số thông tin vào thông báo lỗi để người dùng hiểu được lỗi gì

Chúc mừng và lập trình vui vẻ
winklerrr


[Tôi biết câu hỏi này đã được trả lời và đây không chính xác là câu hỏi mà người khởi động chủ đề đã hỏi, nhưng tôi đến đây vì vấn đề trên dẫn đến cùng một thông báo lỗi. Ít nhất tôi đã mất khá nhiều thời gian để tìm ra lỗi đánh máy nhỏ đó.

Vì vậy, tôi hy vọng rằng điều này sẽ giúp người khác vấp phải lỗi tương tự và tiết kiệm cho họ một chút thời gian để tìm ra lỗi nhỏ đó.]


0

Điều này có thể xảy ra nếu thiếu dấu phẩy. Tôi tình cờ gặp nó khi tôi có một danh sách gồm hai bộ dữ liệu, mỗi bộ gồm một chuỗi ở vị trí đầu tiên và một danh sách ở vị trí thứ hai. Tôi đã bỏ sót dấu phẩy sau thành phần đầu tiên của một tuple trong một trường hợp và trình thông dịch nghĩ rằng tôi đang cố gắng lập chỉ mục thành phần đầu tiên.


0

Tôi gặp vấn đề tương tự với Pandas, bạn cần sử dụng hàm iterrows () để lặp qua tài liệu Pandas của bộ dữ liệu Pandas cho iterrows

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

lưu ý rằng bạn cần xử lý chỉ mục trong tập dữ liệu cũng được trả về bởi hàm.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.