Why am I seeing "TypeError: string indices must be integers"?
item
is most likely a string in your code; the string indices are the ones in the square brackets, e.g., gravatar_id
. So I'd first check your data
variable to see what you received there; I guess that data
is a list of strings (or at least a list containing at least one string) while it should be a list of dictionaries.
The variable item
is a string. An index looks like this:
>>> mystring = 'helloworld'
>>> print mystring[0]
'h'
The above example uses the 0
index of the string to refer to the first character.
Strings can't have string indices (like dictionaries can). So this won't work:
>>> mystring = 'helloworld'
>>> print mystring['stringindex']
TypeError: string indices must be integers
TypeError for Slice Notation str[a:b]
Short Answer
Use a colon :
instead of a comma ,
in between the two indices a
and b
in str[a:b]
:
my_string[0,5] # wrong ❌
my_string[0:5] # correct ✅
Long Answer
When working with strings and slice notation (a common sequence operation), it can happen that a TypeError
is raised, pointing out that the indices must be integers, even if they obviously are.
Example
>>> my_string = "Hello, World!"
>>> my_string[0,5]
TypeError: string indices must be integers
We obviously passed two integers for the indices to the slice notation, right? So what is the problem here?
This error can be very frustrating - especially at the beginning of learning Python - because the error message is a little bit misleading.
Explanation
We implicitly passed a tuple
of two integers to the slice notation when we called my_string[0,5]
. 0,5
evaluates to the same tuple as (0,5)
does - even without the parentheses. Why though?
A trailing comma ,
is actually enough for the Python interpreter to evaluate something as a tuple:
>>> my_variable = 0,
>>> type(my_variable)
<class 'tuple'>
So what we did there, this time explicitly:
>>> my_string = "Hello, World!"
>>> my_tuple = 0, 5
>>> my_string[my_tuple]
TypeError: string indices must be integers
Now, at least, the error message makes sense.
Solution
We need to replace the comma ,
with a colon :
to separate the two integers correctly, not having them interpreted as a tuple
:
>>> my_string = "Hello, World!"
>>> my_string[0:5]
'hello'
A clearer and more helpful error message could have been something like:
TypeError: string indices must be integers not tuple
^^^^^
(actual type here)
A good error message should show the user directly what they did wrong! With this kind of information it would have been much more easier to find the root cause and solve the problem - and you wouldn't have had to come here.
So next time, when you find yourself responsible for writing error description messages, remind yourself of this example and add the reason (or other useful information) to error message! Help other people (or maybe even your future self) to understand what went wrong.
Lessons learned
- slice notation uses colons
:
to separate its indices (and step range, i.e.,str[from:to:step]
) - tuples are defined by commas
,
(i.e.,t = 1,
) - add some information to error messages for users to understand what went wrong