How can I understand and fix the problem?
First, look at the traceback to see where in the code the error occurs. If it's in a library, work backwards to the point where your code uses the library. Then read the error message carefully, and compare it to the code, to figure out what causes the complaint. Finally, think carefully: is the operation wrong, or the values?
Examples
(TODO)
Some non-obvious things
Reusing names
Did you perhaps reassign the name of a built-in callable, such as str
or input
or list
? Did you try to reuse a name for two different things (for example, a function and some global data that it uses)?
Names in Python can only refer to one thing at a time. If you use, say, list
as a variable name, then it isn't also the name of "the abstract concept of a list" any more, so you can't use it to create more lists (which includes converting other things to lists). If you create a global variable months
with a list of strings, and then write a function months
, the function replaces the list, and the function's code can't look up the list. This can easily happen accidentally when using from some_module import *
syntax.
Similarly, if you try to make a class that uses the same name for an method as for a data attribute of the instances, that will cause the same problem. (There's also a tricky special case with @staticmethod
).
Processing lists
Sometimes people expect to be able to use a list like a Numpy array, and "broadcast" an operation or a function call to each element of the list. That doesn't work. Use a list comprehension instead.
Handling None
Consider whether you need to handle None
as a special case. But try to avoid getting into that situation in the first place; "special cases aren't special enough to break the rules", as they say.
Trying to use a library (including a standard library)
If something doesn't work like you'd expect (for example, trying to subtract datetime.time
s or serialize an instance of a user-defined class as JSON) - rather than trying to treat the problem as a debugging question, search for solutions for what you want that part of the code to do.
If the error mentions a 'str' type and you thought it should be a number
Did you get it from the input
function? That gives you a str
, even if it looks like a number. Please see How can I read inputs as numbers?.
If the error mentions a 'function' type or 'type' type
Did you forget to call the function, or create an instance of a class?
Error messages about wrong arguments
The error message will tell you the name of the function; so look at the part of the line that calls that function, and check the arguments. Is there a correct number of positional arguments? Is there a keyword argument that must be provided, and is missing? Is there a keyword argument that shouldn't be provided? Is there a positional argument that is also provided by keyword?
If you are writing a method for a class, remember to allow for self
. It is necessary for instance methods. If you are calling a method, keep in mind that self
will be counted as an argument (both for the amount "required" and the amount "given").
A common beginner error is attempting to use a method (which
isn't a classmethod
) from a class without instantiating it. You'd do something like
value = MyClass.method(things)
where you should be doing something like
instance = MyCLass()
value = instance.method(things)
which (obscurely) passes instance
as the first (self
) argument to method
, and things
as the second argument.
If you are using a callback that takes arguments from an indirect source, check the source.
If you are trying to create an instance of your own class, and get an TypeError
from __init__
, make sure that you actually wrote an __init__
.
If you don't know what the arguments should be, check the documentation. If the arguments make sense, maybe the function is wrong - make sure you didn't confuse it for another one in the same library.
Error messages about operand types
Make sure the operator is correct for what you want the code to do (for example: ^
is not exponentiation; you want **
), and then check the operand types.
In most cases, it will be appropriate to convert the type - but think carefully. Make sure the operation will make sense with the new types. For example, if the code is l + 'second'
, and l
is a list
that currently contains ['first']
, chances are good we don't want to concatenate strings, but instead create a modified list that also has 'second'
as an element. So actually we wanted to "add" another list: l + ['second']
.
If string indices must be integers
, it could be that the string being indexed is JSON or something of that sort, which should have been parsed already to create a dictionary (possibly with nested lists and dictionaries).
If list indices must be integers or slices
, it's likely that the problem is with the list
, rather than the index. If you expected the list
to be a dict
, check whether it contains a dict
- especially if it contains exactly one element, which is a dict
. Then check if that's the dict
that should actually be looked into. If so, the solution is easy: simply add another level of indexing, in order to grab that dict
first. This commonly happens when trying to grab data from parsed JSON.
Error messages about string formatting
Seriously, did you intend to do string formatting? If you do want to format a string, consider using f-strings or the .format
method - these are easier to debug, and have fewer special cases. But more likely, the left-hand side is some string like '1'
that should have been converted to int
(or maybe float
) first.
Error messages about a "descriptor"
Python's error message here is fairly cryptic - it's using terminology that most programmers rarely if ever have to worry about. But once recognized, the error is very easy to pattern-match. Take special care if the class can be instantiated with no arguments - an empty pair of parentheses ()
is still necessary to instantiate the class; otherwise, the code refers to the class itself. An instance is required in order to use methods.
Custom error messages from built-in functions
A "bad operand" for a "unary" operator (for example bad operand type for unary +: 'str'
) can be caused by a stray comma. 'a', + 'b'
is not the same as 'a' + 'b'
; it is trying to use +
as a unary operator on the 'b'
string, and then make a tuple. (You know how you can write e.g. -1
to get a negative number? The -
there is a unary operator. It turns out you can similarly write +1
; it means the same as 1
, of course.)
Especially if you have had to migrate code from 2.x to 3.x, be very careful about the distinction between bytes
and str
types in 3.x. bytes
represents raw data; str
represents text. These are fundamentally different and unrelated things, and it is only possible to convert from one to the other by using an encoding. In Python 3.x, files that are opened in a binary mode (using 'b'
in the mode string) produce bytes
when read, and must be given something compatible with bytes
when written to. str
does not qualify; you must specify an encoding explicitly. The canonical for this problem is "TypeError: a bytes-like object is required, not 'str'" when handling file content in Python 3.
Error messages where something "is not" usable in some way
Did you want to use it that way?
Python can't read your intent. For example, accessing an element of a list is done using []
, not ()
. If the code says ()
instead, that will be interpreted as an attempt to call the list, so the error message will complain that the list is not callable.
Not iterable
When something is not iterable
, the problem is very likely with the thing, rather than the iteration. If you want a for
loop to run a specific number of times, you still need something to iterate over; a range
is the usual choice. The same is true if you are using a list comprehension etc. to make multiple copies of a value. If you have an integer x
and you want to make a list with one item, which is that integer, that is spelled [x]
, not list(x)
.
It's especially common to see 'NoneType' object is not iterable
. There is exactly one 'NoneType' object
: the special value None
- Python forbids creating any more instances of that class. Python methods that work in-place - especially list methods - generally return None
rather than the list that was modified. See also TypeError: 'NoneType' object is not iterable in Python.
Not callable
If a 'module' object is not callable
, it's most likely because you want a function or class from the module, that has the same name as the module, rather than the module itself. The linked example is for the socket
standard library; other common cases include datetime
and random
.
Also make sure that the code doesn't call a function and remember the result, instead of remembering the function itself. This is a common problem with APIs that expect a "callback" function. (If you need to choose the arguments ahead of time, but not actually call the function, see How can I bind arguments to a function in Python? .) Sometimes people also try to provide the name of a function as a string, rather than providing the function itself.
Beginners sometimes expect to be able to do "implicit multiplication" in a mathematical formula, the way that it works in math class. In a Python program (like other popular languages), code like a(b + c)
does not multiply the integer a
by the result of b + c
; it attempts to call a
as if it were a function. See Why do I get "TypeError: 'int' object is not callable" from code like "5(side_length**2)"?.
Not subscriptable
Sometimes, people try to get "digits" from a number by indexing into it as if it were a string. int
and float
values aren't strings; they don't have digits in them. So this will cause a "is not subscriptable" TypeError
. The numeric value is the same no matter what base you write them in, and there are other ways to write a number besides base ten; so it is your responsibility to create the appropriate string first.
If you are trying to work with nested lists, be careful about indexing into them. A list like example = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
should be indexed like example[i][j]
, not e.g. example[i[j]]
. The logic here should be pretty simple: the correct code means to index into example
(getting a list of integers), and then index into that result. The incorrect code means to use j
as an index into i
first, because of how the brackets are nested.
If you are trying to call a function or use a class (such as the built-in range
), remember that this uses parentheses, not square brackets:
# WRONG
range[10]
# RIGHT
range(10)