Recommended Video Course
Identify Invalid Python Syntax
Table of Contents
Watch Now This tutorial has a related video course created by the Real Python team. Watch it together with the written tutorial to deepen your understanding:Identify Invalid Python Syntax
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 aSyntaxError
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.
By the end of this tutorial, you’ll be able to:
SyntaxError
tracebacksFree 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 run your Python code, the interpreter will first parse it to convert it into Python byte code, which it will then execute. The interpreter will find any invalid syntax in Python during this first stage of program execution, also known as theparsing stage. If the interpreter can’t parse your Python code successfully, then this means that you used invalid syntax somewhere in your code. The interpreter will attempt to show you where that error occurred.
When you’re learning Python for the first time, it can be frustrating to get aSyntaxError
. Python will attempt to help you determine where the invalid syntax is in your code, but thetraceback it provides can be a little confusing. Sometimes, the code it points to is perfectly fine.
Note: If your code issyntactically correct, then you may get other exceptions raised that are not aSyntaxError
. To learn more about Python’s other exceptions and how to handle them, check outPython Exceptions: An Introduction.
You can’t handle invalid syntax in Python like other exceptions. Even if you tried to wrap atry
andexcept
block around code with invalid syntax, you’d still see the interpreter raise aSyntaxError
.
SyntaxError
Exception and TracebackWhen the interpreter encounters invalid syntax in Python code, it will raise aSyntaxError
exception and provide a traceback with some helpful information to help youdebug the error. Here’s some code that contains invalid syntax in Python:
1# theofficefacts.py 2ages={ 3'pam':24, 4'jim':24 5'michael':43 6} 7print(f'Michael is{ages["michael"]} years old.')
You can see the invalid syntax in thedictionary 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:
$pythontheofficefacts.pyFile "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 aSyntaxError
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 after it. For example, there’s no problem with a missing comma after'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’stracebacks. To learn more about the Python traceback and how to read them, check outUnderstanding the Python Traceback andGetting the Most out of a Python Traceback.
There are a few elements of aSyntaxError
traceback that can help you determine where the invalid syntax is in your code:
^
) on the line below the reproduced code, which shows you the point in the code that has a problemSyntaxError
, which can provide information to help you determine the problemIn the example above, the file name given wastheofficefacts.py
, the line number was 5, and the caret pointed to the closing quote of the dictionary keymichael
. TheSyntaxError
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 toSyntaxError
but have different names:
IndentationError
TabError
These exceptions both inherit from theSyntaxError
class, but they’re special cases where indentation is concerned. AnIndentationError
is raised when the indentation levels of your code don’t match up. ATabError
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.
When you encounter aSyntaxError
for the first time, it’s helpful to know why there was a problem and what you might do to fix the invalid syntax in your Python code. In the sections below, you’ll see some of the more common reasons that aSyntaxError
might be raised and how you can fix them.
=
)There are several cases in Python where you’re not able to makeassignments to objects. Some examples are assigning to literals and function calls. In the code block below, you can see a few examples that attempt to do this and the resultingSyntaxError
tracebacks:
>>>len('hello')=5 File"<stdin>", line1SyntaxError:can't assign to function call>>>'foo'=1 File"<stdin>", line1SyntaxError:can't assign to literal>>>1='foo' File"<stdin>", line1SyntaxError:can't assign to literal
The first example tries to assign the value5
to thelen()
call. TheSyntaxError
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 astring 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 different 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 off the extra equals sign (=
), which would turn the assignment into a comparison. A comparison, as you can see below, would be valid:
>>>len('hello')==5True
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 aBoolean expression instead. You may also run into this issue when you’re trying to assign a value to aPython keyword, which you’ll cover in the next section.
Python keywords are a set ofprotected words that have special meaning in Python. These are words you can’t use as identifiers,variables, or function names in your code. They’re a part of the language and can only be used in the context that Python allows.
There are three common ways that you can mistakenly use keywords:
If youmisspell a keyword in your Python code, then you’ll get aSyntaxError
. For example, here’s what happens if you spell the keywordfor
incorrectly:
>>>froiinrange(10): File"<stdin>", line1froiinrange(10):^SyntaxError:invalid syntax
The message readsSyntaxError: 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 youmiss them altogether:
>>>forirange(10): File"<stdin>", line1forirange(10):^SyntaxError:invalid syntax
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 thein
keyword is missing from thefor
loop syntax.
You can alsomisuse 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 ofcontinue
orbreak
outside of a loop. This can easily happen during development when you’re implementing things and happen to move logic outside of a loop:
>>>names=['pam','jim','michael']>>>if'jim'innames:...print('jim found')...break... File"<stdin>", line3SyntaxError:'break' outside loop>>>if'jim'innames:...print('jim found')...continue... File"<stdin>", line3SyntaxError:'continue' not properly in loop
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 todefine a function:
>>>pass=True File"<stdin>", line1pass=True^SyntaxError:invalid syntax>>>defpass(): File"<stdin>", line1defpass():^SyntaxError:invalid syntax
When you attempt to assign a value topass
, or when you attempt to define a new function calledpass
, you’ll get aSyntaxError
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 aSyntaxError
, 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 useawait
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 useawait
as a variable or function name, this will cause aSyntaxError
if your code is for Python 3.7 or later.
Another example of this isprint
, which differs in Python 2 vs Python 3:
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:
importkeywordprint(keyword.kwlist)
keyword
also provides the usefulkeyword.iskeyword()
. If you just need a quick way to check thepass
variable, then you can use the following one-liner:
>>>importkeyword;keyword.iskeyword('pass')True
This code will tell you quickly if the identifier that you’re trying to use is a keyword or not.
Often, the cause of invalid syntax in Python code is a missed or mismatched closing parenthesis, bracket, or quote. These can be hard to spot in very long lines of nested parentheses or longer multi-line blocks. You can spot mismatched or missing quotes with the help of Python’s tracebacks:
>>>message='don't' File"<stdin>", line1message='don't'^SyntaxError:invalid syntax
Here, the traceback points to the invalid code where there’s at'
after a closing single quote. To fix this, you can make one of two changes:
'don\'t'
)"don't"
)Another common mistake is to forget to close string. With both double-quoted and single-quoted strings, the situation and traceback are the same:
>>>message="This is an unclosed string File"<stdin>", line1message="This is an unclosed string^SyntaxError:EOL while scanning string literal
This time, the caret in the traceback points right to the problem code. TheSyntaxError
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 anf-string can also lead to invalid syntax in Python:
1# theofficefacts.py 2ages={ 3'pam':24, 4'jim':24, 5'michael':43 6} 7print(f'Michael is{ages["michael]} years old.')
Here, the reference to theages
dictionary inside the printed f-string is missing the closing double quote from the key reference. The resulting traceback is as follows:
$pythontheofficefacts.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 alist, 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 off of the list:
# missing.pydeffoo():return[1,2,3print(foo())
When you run this code, you’ll be told that there’s a problem with the call toprint()
:
$pythonmissing.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
, and3 print(foo())
. Python useswhitespace to group things logically, and because there’s no comma or bracket separating3
fromprint(foo())
, Python lumps them together as the third element of the list.
Another variation is to add a trailing comma after the last element in the list while still leaving off the closing square bracket:
# missing.pydeffoo():return[1,2,3,print(foo())
Now you get a different traceback:
$pythonmissing.py File "missing.py", line 6 ^SyntaxError: unexpected EOF while parsing
In the previous example,3
andprint(foo())
were lumped together as one element, but here you see a comma separating the two. Now, the call toprint(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.
You sawearlier that you could get aSyntaxError
if you leave the comma off of a dictionary element. Another form of invalid syntax with Python dictionaries is the use of the equals sign (=
) to separate keys and values, instead of the colon:
>>>ages={'pam'=24} File"<stdin>", line1ages={'pam'=24}^SyntaxError:invalid syntax
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 adict()
call. To fix this, you could replace the equals sign with a colon. You can also switch to usingdict()
:
>>>ages=dict(pam=24)>>>ages{'pam': 24}
You can usedict()
to define the dictionary if that syntax is more helpful.
There are two sub-classes ofSyntaxError
that deal with indentation issues specifically:
IndentationError
TabError
While other programming languages use curly braces to denote blocks of code, Python useswhitespace. That means that Python expects the whitespace in your code to behave predictably. It will raise anIndentationError
if there’s a line in a code block that has the wrong number of spaces:
1# indentation.py 2deffoo(): 3foriinrange(10): 4print(i) 5print('done') 6 7foo()
This might be tough to see, but line 5 is only indented 2 spaces. It should be in line with thefor
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 theprint('done')
line intended to beafter thefor
loop orinside thefor
loop block? When you run the above code, you’ll see the following error:
$pythonindentation.py File "indentation.py", line 5 print('done') ^IndentationError: unindent does not match any outer indentation level
Even though the traceback looks a lot like theSyntaxError
traceback, it’s actually anIndentationError
. 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 ofSyntaxError
is theTabError
, 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:
1# indentation.py 2deffoo(): 3foriinrange(10): 4print(i) 5print('done') 6 7foo()
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 different tab width settings:
$tabs4# Sets the shell tab width to 4 spaces$cat-nindentation.py 1 # indentation.py 2 def foo(): 3 for i in range(10) 4 print(i) 5 print('done') 6 7 foo()$tabs8# Sets the shell tab width to 8 spaces (standard)$cat-nindentation.py 1 # indentation.py 2 def foo(): 3 for i in range(10) 4 print(i) 5 print('done') 6 7 foo()$tabs3# Sets the shell tab width to 3 spaces$cat-nindentation.py 1 # indentation.py 2 def foo(): 3 for i in range(10) 4 print(i) 5 print('done') 6 7 foo()
Notice the difference 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 thetab width setting:
print
statement will look like it’s outside thefor
loop. The console will print'done'
at the end of the loop.print
statement will look like it’s inside thefor
loop. The console will print'done'
after each number.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:
$pythonindentation.py File "indentation.py", line 5 print('done') ^TabError: inconsistent use of tabs and spaces in indentation
Notice theTabError
instead of the usualSyntaxError
. 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'
after thefor
loop has finished.
You might run into invalid syntax in Python when you’re defining or calling functions. For example, you’ll see aSyntaxError
if you use a semicolon instead of a colon at the end of a function definition:
>>>deffun(); File"<stdin>", line1deffun();^SyntaxError:invalid syntax
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 argumentsalways come after positional arguments. Failure to use this ordering will lead to aSyntaxError
:
>>>deffun(a,b):...print(a,b)...>>>fun(a=1,2) File"<stdin>", line1SyntaxError:positional argument follows keyword argument
Here, once again, the error message is very helpful in telling you exactly what is wrong with the line.
Sometimes, code that works perfectly fine in one version of Python breaks in a newer version. This is due to official changes in language syntax. The most well-known example of this is theprint
statement, which went from a keyword in Python 2 to a built-in function in Python 3:
>>># Valid Python 2 syntax that fails in Python 3>>>print'hello' File"<stdin>", line1print'hello'^SyntaxError:Missing parentheses in call to 'print'. Did you mean print('hello')?
This is one of the examples where the error message provided with theSyntaxError
shines! Not only does it tell you that you’re missing parenthesis in theprint
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 thef-string syntax, which doesn’t exist in Python versions before 3.6:
>>># Any version of python before 3.6 including 2.7>>>w='world'>>>print(f'hello,{w}') File"<stdin>", line1print(f'hello,{w}')^SyntaxError:invalid syntax
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 codelooks 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 inPython 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 aSyntaxError
.
Python 3.8 also provides the newSyntaxWarning
. 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 aTypeError
because a tuple is not callable:
>>>[(1,2)(2,3)]Traceback (most recent call last): File"<stdin>", line1, in<module>TypeError:'tuple' object is not callable
ThisTypeError
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 theTypeError
, but now you’ll also see aSyntaxWarning
that indicates how you can go about fixing the problem:
>>>[(1,2)(2,3)]<stdin>:1: SyntaxWarning: 'tuple' object is not callable; perhaps you missed a comma?Traceback (most recent call last): File"<stdin>", line1, in<module>TypeError:'tuple' object is not callable
The helpful message accompanying the newSyntaxWarning
even provides a hint ("perhaps you missed a comma?"
) to point you in the right direction!
In this tutorial, you’ve seen what information theSyntaxError
traceback gives you. You’ve also seen many common 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 anIDE 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 aSyntaxError
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 aSyntaxError
, you’ll be better equipped to fix the problem quickly!
Watch Now This tutorial has a related video course created by the Real Python team. Watch it together with the written tutorial to deepen your understanding:Identify Invalid Python Syntax
🐍 Python Tricks 💌
Get a short & sweetPython Trick delivered to your inbox every couple of days. No spam ever. Unsubscribe any time. Curated by the Real Python team.
AboutChad Hansen
Chad is an avid Pythonista and does web development with Django fulltime. Chad lives in Utah with his wife and six kids.
» More about ChadMasterReal-World Python Skills With Unlimited Access to Real Python
Join us and get access to thousands of tutorials, hands-on video courses, and a community of expert Pythonistas:
MasterReal-World Python Skills
With Unlimited Access to Real Python
Join us and get access to thousands of tutorials, hands-on video courses, and a community of expert Pythonistas:
What Do You Think?
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.
Commenting Tips: The most useful comments are those written with the goal of learning from or helping out other students.Get tips for asking good questions andget answers to common questions in our support portal.
Keep Learning
Recommended Video Course:Identify Invalid Python Syntax
Related Tutorials:
Already have an account?Sign-In
Almost there! Complete this form and click the button below to gain instant access:
5 Thoughts On Python Mastery