Professional Documents
Culture Documents
Invalid Syntax in Python - Common Reasons For SyntaxError - Real Python
Invalid Syntax in Python - Common Reasons For SyntaxError - Real Python
SyntaxError
by Chad Hansen Nov 20, 2019 1 Comment basics python
Table of Contents
Invalid Syntax in Python
SyntaxError Exception and Traceback
Common Syntax Problems
Misusing the Assignment Operator (=)
Misspelling, Missing, or Misusing Python Keywords
Missing Parentheses, Brackets, and Quotes
Mistaking Dictionary Syntax
Using the Wrong Indentation
Defining and Calling Functions
Changing Python Versions
Conclusion
Python is known for its simple syntax. However, when you’re learning Python for the first time or when you’ve come
to Python with a solid background in another programming language, you may run into some things that Python
doesn’t allow. If you’ve ever received a SyntaxError when trying to run your Python code, then this guide can help
you. Throughout this tutorial, you’ll see common examples of invalid syntax in Python and learn how to resolve the
issue.
Free Bonus: 5 Thoughts On Python Mastery, a free course for Python developers that shows you the roadmap
and the mindset you'll need to take your Python skills to the next level.
When you’re learning Python for the first time, it can be frustrating to get a SyntaxError. Python will attempt to help
you determine where the invalid syntax is in your code, but the traceback it provides can be a little confusing.
Sometimes, the code it points to is perfectly fine.
Note: If your code is syntactically correct, then you may get other exceptions raised that are not a SyntaxError.
To learn more about Python’s other exceptions and how to handle them, check out Python Exceptions: An
Introduction.
You can’t handle invalid syntax in Python like other exceptions. Even if you tried to wrap a try and except block
around code with invalid syntax, you’d still see the interpreter raise a SyntaxError.
Python
1 # theofficefacts.py
2 ages = {
3 'pam': 24,
4 'jim': 24
5 'michael': 43
6 }
7 print(f'Michael is {ages["michael"]} years old.')
You can see the invalid syntax in the dictionary literal on line 4. The second entry, 'jim', is missing a comma. If you
tried to run this code as-is, then you’d get the following traceback:
Shell
$ python theofficefacts.py
File "theofficefacts.py", line 5
'michael': 43
^
SyntaxError: invalid syntax
Note that the traceback message locates the error in line 5, not line 4. The Python interpreter is attempting to point
out where the invalid syntax is. However, it can only really point to where it first noticed a problem. When you get a
SyntaxError traceback and the code that the traceback is pointing to looks fine, then you’ll want to start moving
backward through the code until you can determine what’s wrong.
In the example above, there isn’t a problem with leaving out a comma, depending on what comes a er it. For
example, there’s no problem with a missing comma a er 'michael' in line 5. But once the interpreter encounters
something that doesn’t make sense, it can only point you to the first thing it found that it couldn’t understand.
Note: This tutorial assumes that you know the basics of Python’s tracebacks. To learn more about the Python
b k dh d h h k U d di h P h T b k
traceback and how to read them, check out Understanding the Python Traceback.
There are a few elements of a SyntaxError traceback that can help you determine where the invalid syntax is in your
code:
In the example above, the file name given was theofficefacts.py, the line number was 5, and the caret pointed to
the closing quote of the dictionary key michael. The SyntaxError traceback might not point to the real problem, but
it will point to the first place where the interpreter couldn’t make sense of the syntax.
There are two other exceptions that you might see Python raise. These are equivalent to SyntaxError but have
di erent names:
1. IndentationError
2. TabError
These exceptions both inherit from the SyntaxError class, but they’re special cases where indentation is concerned.
An IndentationError is raised when the indentation levels of your code don’t match up. A TabError is raised when
your code uses both tabs and spaces in the same file. You’ll take a closer look at these exceptions in a later section.
Python >>>
>>> len('hello') = 5
File "<stdin>", line 1
SyntaxError: can't assign to function call
>>> 'foo' = 1
File "<stdin>", line 1
SyntaxError: can't assign to literal
>>> 1 = 'foo'
File "<stdin>", line 1
SyntaxError: can't assign to literal
The first example tries to assign the value 5 to the len() call. The SyntaxError message is very helpful in this case. It
tells you that you can’t assign a value to a function call.
The second and third examples try to assign a string and an integer to literals. The same rule is true for other literal
values. Once again, the traceback messages indicate that the problem occurs when you attempt to assign a value to a
literal.
Note: The examples above are missing the repeated code line and caret (^) pointing to the problem in the
traceback. The exception and traceback you see will be di erent when you’re in the REPL vs trying to execute
this code from a file. If this code were in a file, then you’d get the repeated code line and caret pointing to the
problem, as you saw in other cases throughout this tutorial.
It’s likely that your intent isn’t to assign a value to a literal or a function call. For instance, this can occur if you
accidentally leave o the extra equals sign (=), which would turn the assignment into a comparison. A comparison, as
you can see below, would be valid:
Python >>>
>>> len('hello') == 5
True
Most of the time, when Python tells you that you’re making an assignment to something that can’t be assigned to, you
first might want to check to make sure that the statement shouldn’t be a Boolean expression instead. You may also
run into this issue when you’re trying to assign a value to a Python keyword, which you’ll cover in the next section.
There are three common ways that you can mistakenly use keywords:
1. Misspelling a keyword
2. Missing a keyword
3. Misusing a keyword
If you misspell a keyword in your Python code, then you’ll get a SyntaxError. For example, here’s what happens if
you spell the keyword for incorrectly:
Python >>>
The message reads SyntaxError: invalid syntax, but that’s not very helpful. The traceback points to the first place
where Python could detect that something was wrong. To fix this sort of error, make sure that all of your Python
keywords are spelled correctly.
Another common issue with keywords is when you miss them altogether:
Python >>>
Once again, the exception message isn’t that helpful, but the traceback does attempt to point you in the right
direction. If you move back from the caret, then you can see that the in keyword is missing from the for loop syntax.
You can also misuse a protected Python keyword. Remember, keywords are only allowed to be used in specific
You can also misuse a protected Python keyword. Remember, keywords are only allowed to be used in specific
situations. If you use them incorrectly, then you’ll have invalid syntax in your Python code. A common example of this
is the use of continue or break outside of a loop. This can easily happen during development when you’re
implementing things and happen to move logic outside of a loop:
Python >>>
Here, Python does a great job of telling you exactly what’s wrong. The messages "'break' outside loop" and
"'continue' not properly in loop" help you figure out exactly what to do. If this code were in a file, then Python
would also have the caret pointing right to the misused keyword.
Another example is if you attempt to assign a Python keyword to a variable or use a keyword to define a function:
Python >>>
When you attempt to assign a value to pass, or when you attempt to define a new function called pass, you’ll get a
SyntaxError and see the "invalid syntax" message again.
It might be a little harder to solve this type of invalid syntax in Python code because the code looks fine from the
outside. If your code looks good, but you’re still getting a SyntaxError, then you might consider checking the variable
name or function name you want to use against the keyword list for the version of Python that you’re using.
The list of protected keywords has changed with each new version of Python. For example, in Python 3.6 you could
use await as a variable name or function name, but as of Python 3.7, that word has been added to the keyword list.
Now, if you try to use await as a variable or function name, this will cause a SyntaxError if your code is for Python 3.7
or later.
Python 2 keyword no
print is a keyword in Python 2, so you can’t assign a value to it. In Python 3, however, it’s a built-in function that can
be assigned values.
You can run the following code to see the list of keywords in whatever version of Python you’re running:
Python
import keyword
print(keyword.kwlist)
keyword also provides the useful keyword.iskeyword(). If you just need a quick way to check the pass variable, then
you can use the following one-liner:
Python >>>
This code will tell you quickly if the identifier that you’re trying to use is a keyword or not.
Python >>>
Here, the traceback points to the invalid code where there’s a t' a er a closing single quote. To fix this, you can make
one of two changes:
Another common mistake is to forget to close string. With both double-quoted and single-quoted strings, the
situation and traceback are the same:
Python >>>
This time, the caret in the traceback points right to the problem code. The SyntaxError message, "EOL while
scanning string literal", is a little more specific and helpful in determining the problem. This means that the
Python interpreter got to the end of a line (EOL) before an open string was closed. To fix this, close the string with a
quote that matches the one you used to start it. In this case, that would be a double quote (").
Quotes missing from statements inside an f-string can also lead to invalid syntax in Python:
Python
1 # theofficefacts.py
2 ages = {
3 'pam': 24,
4 'jim': 24,
5 'michael': 43
6 }
7 print(f'Michael is {ages["michael]} years old.')
Here, the reference to the ages dictionary inside the printed f-string is missing the closing double quote from the key
reference. The resulting traceback is as follows:
Shell
$ python theofficefacts.py
File "theofficefacts.py", line 7
print(f'Michael is {ages["michael]} years old.')
^
SyntaxError: f-string: unterminated string
Python identifies the problem and tells you that it exists inside the f-string. The message "unterminated string"
also indicates what the problem is. The caret in this case only points to the beginning of the f-string.
This might not be as helpful as when the caret points to the problem area of the f-string, but it does narrow down
where you need to look. There’s an unterminated string somewhere inside that f-string. You just have to find out
where. To fix this problem, make sure that all internal f-string quotes and brackets are present.
The situation is mostly the same for missing parentheses and brackets. If you leave out the closing square bracket
from a list, for example, then Python will spot that and point it out. There are a few variations of this, however. The
first is to leave the closing bracket o of the list:
Python
# missing.py
def foo():
return [1, 2, 3
print(foo())
When you run this code, you’ll be told that there’s a problem with the call to print():
Shell
$ python missing.py
File "missing.py", line 5
print(foo())
^
SyntaxError: invalid syntax
What’s happening here is that Python thinks the list contains three elements: 1, 2, and 3 print(foo()). Python uses
whitespace to group things logically, and because there’s no comma or bracket separating 3 from print(foo()),
Python lumps them together as the third element of the list.
Another variation is to add a trailing comma a er the last element in the list while still leaving o the closing square
bracket:
Python
# missing.py
def foo():
return [1, 2, 3,
print(foo())
Shell
$ python missing.py
File "missing.py", line 6
^
SyntaxError: unexpected EOF while parsing
In the previous example, 3 and print(foo()) were lumped together as one element, but here you see a comma
separating the two. Now, the call to print(foo()) gets added as the fourth element of the list, and Python reaches
the end of the file without the closing bracket. The traceback tells you that Python got to the end of the file (EOF), but
it was expecting something else.
In this example, Python was expecting a closing bracket (]), but the repeated line and caret are not very helpful.
Missing parentheses and brackets are tough for Python to identify. Sometimes the only thing you can do is start from
the caret and move backward until you can identify what’s missing or wrong.
Python >>>
Once again, this error message is not very helpful. The repeated line and caret, however, are very helpful! They’re
pointing right to the problem character.
This type of issue is common if you confuse Python syntax with that of other programming languages. You’ll also see
this if you confuse the act of defining a dictionary with a dict() call. To fix this, you could replace the equals sign with
a colon. You can also switch to using dict():
Python >>>
You can use dict() to define the dictionary if that syntax is more helpful.
1. IndentationError
2. TabError
While other programming languages use curly braces to denote blocks of code, Python uses whitespace. That means
that Python expects the whitespace in your code to behave predictably. It will raise an IndentationError if there’s a
line in a code block that has the wrong number of spaces:
Python
1 # indentation.py
2 def foo():
3 for i in range(10):
4 print(i)
5 print('done')
6
7 foo()
This might be tough to see, but line 5 is only indented 2 spaces. It should be in line with the for loop statement, which
is 4 spaces over. Thankfully, Python can spot this easily and will quickly tell you what the issue is.
There’s also a bit of ambiguity here, though. Is the print('done') line intended to be a er the for loop or inside the
for loop block? When you run the above code, you’ll see the following error:
Shell
$ python indentation.py
File "indentation.py", line 5
File indentation.py , line 5
print('done')
^
IndentationError: unindent does not match any outer indentation level
Even though the traceback looks a lot like the SyntaxError traceback, it’s actually an IndentationError. The error
message is also very helpful. It tells you that the indentation level of the line doesn’t match any other indentation
level. In other words, print('done') is indented 2 spaces, but Python can’t find any other line of code that matches
this level of indentation. You can fix this quickly by making sure the code lines up with the expected indentation level.
The other type of SyntaxError is the TabError, which you’ll see whenever there’s a line that contains either tabs or
spaces for its indentation, while the rest of the file contains the other. This might go hidden until Python points it out
to you!
If your tab size is the same width as the number of spaces in each indentation level, then it might look like all the lines
are at the same level. However, if one line is indented using spaces and the other is indented with tabs, then Python
will point this out as a problem:
Python
1 # indentation.py
2 def foo():
3 for i in range(10):
4 print(i)
5 print('done')
6
7 foo()
Here, line 5 is indented with a tab instead of 4 spaces. This code block could look perfectly fine to you, or it could look
completely wrong, depending on your system settings.
Python, however, will notice the issue immediately. But before you run the code to see what Python will tell you is
wrong, it might be helpful for you to see an example of what the code looks like under di erent tab width settings:
Shell
Notice the di erence in display between the three examples above. Most of the code uses 4 spaces for each
indentation level, but line 5 uses a single tab in all three examples. The width of the tab changes, based on the tab
width setting:
If the tab width is 4, then the print statement will look like it’s outside the for loop. The console will print
'done' at the end of the loop.
If the tab width is 8, which is standard for a lot of systems, then the print statement will look like it’s inside the
for loop. The console will print 'done' a er each number.
If the tab width is 3, then the print statement looks out of place. In this case, line 5 doesn’t match up with any
indentation level.
When you run the code, you’ll get the following error and traceback:
Shell
$ python indentation.py
File "indentation.py", line 5
print('done')
^
TabError: inconsistent use of tabs and spaces in indentation
Notice the TabError instead of the usual SyntaxError. Python points out the problem line and gives you a helpful
error message. It tells you clearly that there’s a mixture of tabs and spaces used for indentation in the same file.
The solution to this is to make all lines in the same Python code file use either tabs or spaces, but not both. For the
code blocks above, the fix would be to remove the tab and replace it with 4 spaces, which will print 'done' a er the
for loop has finished.
Python >>>
The traceback here is very helpful, with the caret pointing right to the problem character. You can clear up this invalid
syntax in Python by switching out the semicolon for a colon.
In addition, keyword arguments in both function definitions and function calls need to be in the right order. Keyword
arguments always come a er positional arguments. Failure to use this ordering will lead to a SyntaxError:
Python >>>
Here, once again, the error message is very helpful in telling you exactly what is wrong with the line.
Python >>>
This is one of the examples where the error message provided with the SyntaxError shines! Not only does it tell you
that you’re missing parenthesis in the print call, but it also provides the correct code to help you fix the statement.
Another problem you might encounter is when you’re reading or learning about syntax that’s valid syntax in a newer
version of Python, but isn’t valid in the version you’re writing in. An example of this is the f-string syntax, which
doesn’t exist in Python versions before 3.6:
Python >>>
In versions of Python before 3.6, the interpreter doesn’t know anything about the f-string syntax and will just provide
a generic "invalid syntax" message. The problem, in this case, is that the code looks perfectly fine, but it was run
with an older version of Python. When in doubt, double-check which version of Python you’re running!
Python syntax is continuing to evolve, and there are some cool new features introduced in Python 3.8:
If you want to try out some of these new features, then you need to make sure you’re working in a Python 3.8
environment. Otherwise, you’ll get a SyntaxError.
Python 3.8 also provides the new SyntaxWarning. You’ll see this warning in situations where the syntax is valid but
still looks suspicious. An example of this would be if you were missing a comma between two tuples in a list. This
would be valid syntax in Python versions before 3.8, but the code would raise a TypeError because a tuple is not
callable:
Python >>>
>>> [(1,2)(2,3)]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'tuple' object is not callable
This TypeError means that you can’t call a tuple like a function, which is what the Python interpreter thinks you’re
doing.
In Python 3.8, this code still raises the TypeError, but now you’ll also see a SyntaxWarning that indicates how you can
go about fixing the problem:
Python >>>
>>> [(1,2)(2,3)]
<stdin>:1: SyntaxWarning: 'tuple' object is not callable; perhaps you missed a comma?
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'tuple' object is not callable
The helpful message accompanying the new SyntaxWarning even provides a hint ("perhaps you missed a comma?")
to point you in the right direction!
Conclusion
In this tutorial, you’ve seen what information the SyntaxError traceback gives you. You’ve also seen many common
,y y g y y
examples of invalid syntax in Python and what the solutions are to those problems. Not only will this speed up your
workflow, but it will also make you a more helpful code reviewer!
When you’re writing code, try to use an IDE that understands Python syntax and provides feedback. If you put many of
the invalid Python code examples from this tutorial into a good IDE, then they should highlight the problem lines
before you even get to execute your code.
Getting a SyntaxError while you’re learning Python can be frustrating, but now you know how to understand
traceback messages and what forms of invalid syntax in Python you might come up against. The next time you get a
SyntaxError, you’ll be better equipped to fix the problem quickly!
🐍 Python Tricks 💌
Get a short & sweet Python Trick delivered to your inbox every couple of
days. No spam ever. Unsubscribe any time. Curated by the Real Python
team.
Email Address
Chad is an avid Pythonista and does web development with Django fulltime. Chad lives in Utah
with his wife and six kids.
Each tutorial at Real Python is created by a team of developers so that it meets our high quality standards. The team members who
worked on this tutorial are:
Joanna Mike
Real Python Comment Policy: The most useful comments are those written with the goal of learning
from or helping out other readers—a er reading the whole article and all the earlier comments.
Complaints and insults generally won’t make the cut here.
What’s your #1 takeaway or favorite thing you learned? How are you going to put your newfound skills to use?
Leave a comment below and let us know.
Keep Learning
🐍 Python Tricks 💌
— FREE Email Series —
Email…
Get Python Tricks »
Table of Contents
Invalid Syntax in Python
SyntaxError Exception and Traceback
Common Syntax Problems
Conclusion