SyntaxError
— это ошибка, которая легко может ввести в ступор начинающего программиста. Стоит забыть одну запятую или не там поставить кавычку и Python наотрез откажется запускать программу. Что ещё хуже, по выводу в консоль сложно сообразить в чём дело. Выглядят сообщения страшно и непонятно. Что с этим делать — не ясно. Вот неполный список того, что можно встретить:
SyntaxError: invalid syntax
SyntaxError: EOL while scanning string literal
SyntaxError: unexpected EOF while parsing
Эта статья о том, как справиться с синтаксической ошибкой SyntaxError
. Дочитайте её до конца и получите безотказный простой алгоритм действий, что поможет вам в трудную минуту — ваш спасательный круг.
Работать будем с программой, которая выводит на экран список учеников. Её код выглядит немного громоздко и, возможно, непривычно. Если не всё написанное вам понятно, то не отчаивайтесь, чтению статьи это не помешает.
students = [
['Егор', 'Кузьмин'],
['Денис', 'Давыдов'],
]
for first_name, last_name in students:
label = 'Имя ученика: {first_name} {last_name}'.format(
first_name = first_name
last_name = last_name
)
print(label)
Ожидается примерно такой результат в консоли:
$ python script.py
Имя ученика: Егор Кузьмин
Имя ученика: Денис Давыдов
Но запуск программы приводит к совсем другому результату. Скрипт сломан:
$ python script.py
File "script.py", line 9
last_name = last_name
^
SyntaxError: invalid syntax
Ошибки в программе бывают разные и каждой нужен свой особый подход. Первым делом внимательно посмотрите на вывод программы в консоль. На последней строчке написано SyntaxError: invalid syntax
. Если эти слова вам не знакомы, то обратитесь за переводом к Яндекс.Переводчику:
SyntaxError: недопустимый синтаксис
SyntaxError: неверный синтаксис
Первое слово SyntaxError
Яндекс не понял. Помогите ему и разделите слова пробелом:
Syntax Error: invalid syntax
Синтаксическая ошибка: неверный синтаксис
Теория. Синтаксические ошибки
Программирование — это не магия, а Python — не волшебный шар. Он не умеет предсказывать будущее, у него нет доступа к секретным знаниями, это просто автомат, это программа. Узнайте как она работает, как ищет ошибки в коде, и тогда легко найдете эффективный способ отладки. Вся необходимая теория собрана в этом разделе, дочитайте до конца.
SyntaxError
— это синтаксическая ошибка. Она случается очень рано, еще до того, как Python запустит программу. Вот что делает компьютер, когда вы запускаете скрипт командой python script.py
:
- запускает программу
python
python
считывает текст из файлаscript.py
python
превращает текст программы в инструкцииpython
исполняет инструкции
Синтаксическая ошибка SyntaxError
возникает на четвёртом этапе в момент, когда Python разбирает текст программы на понятные ему компоненты. Сложные выражения в коде он разбирает на простейшие инструкции. Вот пример кода и инструкции для него:
person = {'name': 'Евгений'}
Инструкции:
- создать строку
'Евгений'
- создать словарь
- в словарь добавить ключ
'name'
со значением'Евгений'
- присвоить результат переменной
person
SyntaxError
случается когда Python не смог разбить сложный код на простые инструкции. Зная это, вы можете вручную разбить код на инструкции, чтобы затем проверить каждую из них по отдельности. Ошибка прячется в одной из инструкций.
1. Найдите поломанное выражение
Этот шаг сэкономит вам кучу сил. Найдите в программе сломанный участок кода. Его вам предстоит разобрать на отдельные инструкции. Посмотрите на вывод программы в консоль:
$ python script.py
File "script.py", line 9
last_name = last_name
^
SyntaxError: invalid syntax
Вторая строчка сообщает: File "script.py", line 9
— ошибка в файле script.py
на девятой строчке. Но эта строка является частью более сложного выражения, посмотрите на него целиком:
label = 'Имя ученика: {first_name} {last_name}'.format(
first_name = first_name
last_name = last_name
)
«Девман» — авторская методика обучения программированию. Готовим к работе крутых программистов на Python. Станьте программистом, пройдите продвинутый курс Python.
2. Разбейте выражение на инструкции
В прошлых шагах вы узнали что сломан этот фрагмент кода:
label = 'Имя ученика: {first_name} {last_name}'.format(
first_name = first_name
last_name = last_name
)
Разберите его на инструкции:
- создать строку
'Имя ученика: {first_name} {last_name}'
- получить у строки метод
format
- вызвать функцию с двумя аргументами
- результат присвоить переменной
label
Так выделил бы инструкции программист, но вот Python сделать так не смог и сломался. Пора выяснить на какой инструкции нашла коса на камень.
Теперь ваша задача переписать код так, чтобы в каждой строке программы исполнялось не более одной инструкции из списка выше. Так вы сможете тестировать их по отдельности и облегчите себе задачу. Так выглядит отделение инструкции по созданию строки:
# 1. создать строку
template = 'Имя ученика: {first_name} {last_name}'
label = template.format(
first_name = first_name
last_name = last_name
)
Сразу запустите код, проверьте что ошибка осталась на прежнему месте. Приступайте ко второй инструкции:
# 1. создать строку
template = 'Имя ученика: {first_name} {last_name}'
# 2. получить у строки метод
format = template.format
label = format(
first_name = first_name
last_name = last_name
)
Строка format = template.format
создает новую переменную format
и кладёт в неё функцию. Да, да, это не ошибка! Python разрешает класть в переменные всё что угодно, в том числе и функции. Новая переменная переменная format
теперь работает как обычная функция, и её можно вызвать: format(...)
.
Снова запустите код. Ошибка появится внутри format
. Под сомнением остались две инструкции:
- вызвать функцию с двумя аргументами
- результат присвоить переменной
label
Скорее всего, Python не распознал вызов функции. Проверьте это, избавьтесь от последней инструкции — от создания переменной label
:
# 1. создать строку
template = 'Имя ученика: {first_name} {last_name}'
# 2. получить у строки метод
format = template.format
# 3. вызвать функцию
format(
first_name = first_name
last_name = last_name
)
Запустите код. Ошибка снова там же — внутри format
. Выходит, код вызова функции написан с ошибкой, Python не смог его превратить в инструкцию.
3. Проверьте синтаксис вызова функции
Теперь вы знаете что проблема в коде, вызывающем функцию. Можно помедитировать еще немного над кодом программы, пройтись по нему зорким взглядом еще разок в надежде на лучшее. А можно поискать в сети примеры кода для сравнения.
Запросите у Яндекса статьи по фразе “Python синтаксис функции”, а в них поищите код, похожий на вызов format
и сравните. Вот одна из первых статей в поисковой выдаче:
- Функции в Python
Уверен, теперь вы нашли ошибку. Победа!
What are the syntax errors?
PHP belongs to the C-style and imperative programming languages. It has rigid grammar rules, which it cannot recover from when encountering misplaced symbols or identifiers. It can’t guess your coding intentions.
Most important tips
There are a few basic precautions you can always take:
-
Use proper code indentation, or adopt any lofty coding style.
Readability prevents irregularities. -
Use an IDE or editor for PHP with syntax highlighting.
Which also help with parentheses/bracket balancing. -
Read the language reference and examples in the manual.
Twice, to become somewhat proficient.
How to interpret parser errors
A typical syntax error message reads:
Parse error: syntax error, unexpected T_STRING, expecting ‘
;
‘ in file.php on line 217
Which lists the possible location of a syntax mistake. See the mentioned file name and line number.
A moniker such as T_STRING
explains which symbol the parser/tokenizer couldn’t process finally. This isn’t necessarily the cause of the syntax mistake, however.
It’s important to look into previous code lines as well. Often syntax errors are just mishaps that happened earlier. The error line number is just where the parser conclusively gave up to process it all.
Solving syntax errors
There are many approaches to narrow down and fix syntax hiccups.
-
Open the mentioned source file. Look at the mentioned code line.
-
For runaway strings and misplaced operators, this is usually where you find the culprit.
-
Read the line left to right and imagine what each symbol does.
-
-
More regularly you need to look at preceding lines as well.
-
In particular, missing
;
semicolons are missing at the previous line ends/statement. (At least from the stylistic viewpoint. ) -
If
{
code blocks}
are incorrectly closed or nested, you may need to investigate even further up the source code. Use proper code indentation to simplify that.
-
-
Look at the syntax colorization!
-
Strings and variables and constants should all have different colors.
-
Operators
+-*/.
should be tinted distinct as well. Else they might be in the wrong context. -
If you see string colorization extend too far or too short, then you have found an unescaped or missing closing
"
or'
string marker. -
Having two same-colored punctuation characters next to each other can also mean trouble. Usually, operators are lone if it’s not
++
,--
, or parentheses following an operator. Two strings/identifiers directly following each other are incorrect in most contexts.
-
-
Whitespace is your friend.
Follow any coding style. -
Break up long lines temporarily.
-
You can freely add newlines between operators or constants and strings. The parser will then concretize the line number for parsing errors. Instead of looking at the very lengthy code, you can isolate the missing or misplaced syntax symbol.
-
Split up complex
if
statements into distinct or nestedif
conditions. -
Instead of lengthy math formulas or logic chains, use temporary variables to simplify the code. (More readable = fewer errors.)
-
Add newlines between:
- The code you can easily identify as correct,
- The parts you’re unsure about,
- And the lines which the parser complains about.
Partitioning up long code blocks really helps to locate the origin of syntax errors.
-
-
Comment out offending code.
-
If you can’t isolate the problem source, start to comment out (and thus temporarily remove) blocks of code.
-
As soon as you got rid of the parsing error, you have found the problem source. Look more closely there.
-
Sometimes you want to temporarily remove complete function/method blocks. (In case of unmatched curly braces and wrongly indented code.)
-
When you can’t resolve the syntax issue, try to rewrite the commented out sections from scratch.
-
-
As a newcomer, avoid some of the confusing syntax constructs.
-
The ternary
? :
condition operator can compact code and is useful indeed. But it doesn’t aid readability in all cases. Prefer plainif
statements while unversed. -
PHP’s alternative syntax (
if:
/elseif:
/endif;
) is common for templates, but arguably less easy to follow than normal{
code}
blocks.
-
-
The most prevalent newcomer mistakes are:
-
Missing semicolons
;
for terminating statements/lines. -
Mismatched string quotes for
"
or'
and unescaped quotes within. -
Forgotten operators, in particular for the string
.
concatenation. -
Unbalanced
(
parentheses)
. Count them in the reported line. Are there an equal number of them?
-
-
Don’t forget that solving one syntax problem can uncover the next.
-
If you make one issue go away, but other crops up in some code below, you’re mostly on the right path.
-
If after editing a new syntax error crops up in the same line, then your attempted change was possibly a failure. (Not always though.)
-
-
Restore a backup of previously working code, if you can’t fix it.
- Adopt a source code versioning system. You can always view a
diff
of the broken and last working version. Which might be enlightening as to what the syntax problem is.
- Adopt a source code versioning system. You can always view a
-
Invisible stray Unicode characters: In some cases, you need to use a hexeditor or different editor/viewer on your source. Some problems cannot be found just from looking at your code.
-
Try
grep --color -P -n "[x80-xFF]" file.php
as the first measure to find non-ASCII symbols. -
In particular BOMs, zero-width spaces, or non-breaking spaces, and smart quotes regularly can find their way into the source code.
-
-
Take care of which type of linebreaks are saved in files.
-
PHP just honors n newlines, not r carriage returns.
-
Which is occasionally an issue for MacOS users (even on OS X for misconfigured editors).
-
It often only surfaces as an issue when single-line
//
or#
comments are used. Multiline/*...*/
comments do seldom disturb the parser when linebreaks get ignored.
-
-
If your syntax error does not transmit over the web:
It happens that you have a syntax error on your machine. But posting the very same file online does not exhibit it anymore. Which can only mean one of two things:-
You are looking at the wrong file!
-
Or your code contained invisible stray Unicode (see above).
You can easily find out: Just copy your code back from the web form into your text editor.
-
-
Check your PHP version. Not all syntax constructs are available on every server.
-
php -v
for the command line interpreter -
<?php phpinfo();
for the one invoked through the webserver.
Those aren’t necessarily the same. In particular when working with frameworks, you will them to match up.
-
-
Don’t use PHP’s reserved keywords as identifiers for functions/methods, classes or constants.
-
Trial-and-error is your last resort.
If all else fails, you can always google your error message. Syntax symbols aren’t as easy to search for (Stack Overflow itself is indexed by SymbolHound though). Therefore it may take looking through a few more pages before you find something relevant.
Further guides:
- PHP Debugging Basics by David Sklar
- Fixing PHP Errors by Jason McCreary
- PHP Errors – 10 Common Mistakes by Mario Lurig
- Common PHP Errors and Solutions
- How to Troubleshoot and Fix your WordPress Website
- A Guide To PHP Error Messages For Designers – Smashing Magazine
White screen of death
If your website is just blank, then typically a syntax error is the cause.
Enable their display with:
error_reporting = E_ALL
display_errors = 1
In your php.ini
generally, or via .htaccess
for mod_php,
or even .user.ini
with FastCGI setups.
Enabling it within the broken script is too late because PHP can’t even interpret/run the first line. A quick workaround is crafting a wrapper script, say test.php
:
<?php
error_reporting(E_ALL);
ini_set("display_errors", 1);
include("./broken-script.php");
Then invoke the failing code by accessing this wrapper script.
It also helps to enable PHP’s error_log
and look into your webserver’s error.log
when a script crashes with HTTP 500 responses.
Ситуация: программист взял в работу математический проект — ему нужно написать код, который будет считать функции и выводить результаты. В задании написано:
«Пусть у нас есть функция f(x,y) = xy, которая перемножает два аргумента и возвращает полученное значение».
Программист садится и пишет код:
a = 10
b = 15
result = 0
def fun(x,y):
return x y
result = fun(a,b)
print(result)
Но при выполнении такого кода компьютер выдаёт ошибку:
File "main.py", line 13
result = x y
^
❌ SyntaxError: invalid syntax
Почему так происходит: в каждом языке программирования есть свой синтаксис — правила написания и оформления команд. В Python тоже есть свой синтаксис, по которому для умножения нельзя просто поставить рядом две переменных, как в математике. Интерпретатор находит первую переменную и думает, что ему сейчас объяснят, что с ней делать. Но вместо этого он сразу находит вторую переменную. Интерпретатор не знает, как именно нужно их обработать, потому что у него нет правила «Если две переменные стоят рядом, их нужно перемножить». Поэтому интерпретатор останавливается и говорит, что у него лапки.
Что делать с ошибкой SyntaxError: invalid syntax
В нашем случае достаточно поставить звёздочку (знак умножения в Python) между переменными — это оператор умножения, который Python знает:
a = 10
b = 15
result = 0
def fun(x,y):
return x * y
result = fun(a,b)
print(result)
В общем случае найти источник ошибки SyntaxError: invalid syntax можно так:
- Проверьте, не идут ли у вас две команды на одной строке друг за другом.
- Найдите в справочнике описание команды, которую вы хотите выполнить. Возможно, где-то опечатка.
- Проверьте, не пропущена ли команда на месте ошибки.
Практика
Попробуйте найти ошибки в этих фрагментах кода:
x = 10 y = 15
def fun(x,y):
return x * y
try:
a = 100
b = "PythonRu"
assert a = b
except AssertionError:
print("Исключение AssertionError.")
else:
print("Успех, нет ошибок!")
Вёрстка:
Кирилл Климентьев
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 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.
By the end of this tutorial, you’ll be able to:
- Identify invalid syntax in Python
- Make sense of
SyntaxError
tracebacks - Resolve invalid syntax or prevent it altogether
Invalid Syntax in Python
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 the parsing 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 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.
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
.
SyntaxError
Exception and Traceback
When the interpreter encounters invalid syntax in Python code, it will raise a SyntaxError
exception and provide a traceback with some helpful information to help you debug 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 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:
$ 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 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.
There are a few elements of a SyntaxError
traceback that can help you determine where the invalid syntax is in your code:
- The file name where the invalid syntax was encountered
- The line number and reproduced line of code where the issue was encountered
- A caret (
^
) on the line below the reproduced code, which shows you the point in the code that has a problem - The error message that comes after the exception type
SyntaxError
, which can provide information to help you determine the problem
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 different names:
IndentationError
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.
Common Syntax Problems
When you encounter a SyntaxError
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 a SyntaxError
might be raised and how you can fix them.
Misusing the Assignment Operator (=
)
There are several cases in Python where you’re not able to make assignments 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 resulting SyntaxError
tracebacks:
>>>
>>> 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.
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') == 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.
Misspelling, Missing, or Misusing Python Keywords
Python keywords are a set of protected 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:
- Misspelling a keyword
- Missing a keyword
- 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:
>>>
>>> fro i in range(10):
File "<stdin>", line 1
fro i in range(10):
^
SyntaxError: invalid syntax
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:
>>>
>>> for i range(10):
File "<stdin>", line 1
for i range(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 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 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:
>>>
>>> names = ['pam', 'jim', 'michael']
>>> if 'jim' in names:
... print('jim found')
... break
...
File "<stdin>", line 3
SyntaxError: 'break' outside loop
>>> if 'jim' in names:
... print('jim found')
... continue
...
File "<stdin>", line 3
SyntaxError: '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 to define a function:
>>>
>>> pass = True
File "<stdin>", line 1
pass = True
^
SyntaxError: invalid syntax
>>> def pass():
File "<stdin>", line 1
def pass():
^
SyntaxError: invalid syntax
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.
Another example of this is print
, which differs in Python 2 vs Python 3:
Version | print Type |
Takes A Value |
---|---|---|
Python 2 | keyword | no |
Python 3 | built-in function | yes |
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:
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:
>>>
>>> import keyword; keyword.iskeyword('pass')
True
This code will tell you quickly if the identifier that you’re trying to use is a keyword or not.
Missing Parentheses, Brackets, and Quotes
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>", line 1
message = 'don't'
^
SyntaxError: invalid syntax
Here, the traceback points to the invalid code where there’s a t'
after a closing single quote. To fix this, you can make one of two changes:
- Escape the single quote with a backslash (
'don't'
) - Surround the entire string in double-quotes instead (
"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>", line 1
message = "This is an unclosed string
^
SyntaxError: EOL while scanning string literal
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:
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 the ages
dictionary inside the printed f-string is missing the closing double quote from the key reference. The resulting traceback is as follows:
$ 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 off of the list:
# 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()
:
$ 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 after the last element in the list while still leaving off the closing square bracket:
# missing.py
def foo():
return [1, 2, 3,
print(foo())
Now you get a different traceback:
$ 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.
Mistaking Dictionary Syntax
You saw earlier that you could get a SyntaxError
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>", line 1
ages = {'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 a dict()
call. To fix this, you could replace the equals sign with a colon. You can also switch to using dict()
:
>>>
>>> ages = dict(pam=24)
>>> ages
{'pam': 24}
You can use dict()
to define the dictionary if that syntax is more helpful.
Using the Wrong Indentation
There are two sub-classes of SyntaxError
that deal with indentation issues specifically:
IndentationError
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:
1# indentation.py
2def foo():
3 for i in range(10):
4 print(i)
5 print('done')
6
7foo()
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 after the for
loop or inside the for
loop block? When you run the above code, you’ll see the following error:
$ python indentation.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 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:
1# indentation.py
2def foo():
3 for i in range(10):
4 print(i)
5 print('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:
$ tabs 4 # Sets the shell tab width to 4 spaces
$ cat -n indentation.py
1 # indentation.py
2 def foo():
3 for i in range(10)
4 print(i)
5 print('done')
6
7 foo()
$ tabs 8 # Sets the shell tab width to 8 spaces (standard)
$ cat -n indentation.py
1 # indentation.py
2 def foo():
3 for i in range(10)
4 print(i)
5 print('done')
6
7 foo()
$ tabs 3 # Sets the shell tab width to 3 spaces
$ cat -n indentation.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 the tab width setting:
- If the tab width is 4, then the
print
statement will look like it’s outside thefor
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 thefor
loop. The console will print'done'
after 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:
$ 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'
after the for
loop has finished.
Defining and Calling Functions
You might run into invalid syntax in Python when you’re defining or calling functions. For example, you’ll see a SyntaxError
if you use a semicolon instead of a colon at the end of a function definition:
>>>
>>> def fun();
File "<stdin>", line 1
def fun();
^
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 arguments always come after positional arguments. Failure to use this ordering will lead to a SyntaxError
:
>>>
>>> def fun(a, b):
... print(a, b)
...
>>> fun(a=1, 2)
File "<stdin>", line 1
SyntaxError: positional argument follows keyword argument
Here, once again, the error message is very helpful in telling you exactly what is wrong with the line.
Changing Python Versions
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 the print
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>", line 1
print '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 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:
>>>
>>> # Any version of python before 3.6 including 2.7
>>> w ='world'
>>> print(f'hello, {w}')
File "<stdin>", line 1
print(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 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:
- Walrus operator (assignment expressions)
- F-string syntax for debugging
- Positional-only arguments
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:
>>>
>>> [(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:
>>>
>>> [(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 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!
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
Зарегистрируйтесь для доступа к 15+ бесплатным курсам по программированию с тренажером
О, нет, ошибки! И как с ними справляться
—
Введение в программирование
Видео может быть заблокировано из-за расширений браузера. В статье вы найдете решение этой проблемы.
Транскрипт урока
У вас вечеринка, а закуска кончилась, вы просите подругу что-нибудь купить.
— Эй, можешь сходить в магазин и купить какой-нибудь еды?
Она отвечает:
— Что именно?
Вы говорите:
— Ну, типа чипсы или что-нибудь такое. У нас всё закончилось.
Она отвечает:
— Сколько упаковок чипсов взять?
И у вас уже начинает немного вскипать мозг:
— Да, я не знаю, штук 5.
— А какие чипсы?
И вы так глазами делаете и отвечаете “ааа… забудь”, или решаете идти до конца и объясняете подробно задачу: “Возьми 5 средних пакетов картофельных чипсов со вкусом бекона”.
Десять минут спустя она возвращается с пустыми руками и говорит “у них не было таких чипсов в пакетах среднего размера”.
О “программистах” есть определённые стереотипы и то, что они могут быть слишком конкретными и чересчур дотошными — один из них. Многие думают, что такие люди хорошо разбираются в математике или что-то подобное.
В реальности всё намного сложнее. Не существует всего двух типов людей, спектр типов личности буквально бесконечен. И для некоторых людей программирование немного более органично, потому что компьютеры абсолютно конкретные и абсурдно однозначные. Это совершенно не значит, что если вы считаете, что у вас “нематематический склад ума”, вы не сможете стать хорошим разработчиком. Это значит только, что вам нужно научиться лучше распознавать и понимать, как именно работают компьютеры.
Такой способ поведения компьютеров ведёт ко множеству ошибок. Если вы наберёте console,log
— console запятая log, вместо console точка log, JavaScript скажет “Понятия не имею, что ты имел в виду”.
Вы будете делать ошибки и ваши программы будут содержать ошибки. Жизнь — она такая. Любой программист делает ошибки и это не имеет особого значения. Значение имеет только то, как вы потом с ними справляетесь. Исправление ошибок — важный навык. Это делает программирование непохожим на другие типы работ: ошибки неизбежны, вы не можете от них полностью застраховаться, а исправление ошибок — часть вашей работы.
Ошибка вроде “запятая вместо точки” это тип, который проще всего заметить и исправить. Это “синтаксическая ошибка”, потому что неверный символ, как запятая в этом случае, нарушает синтаксические правила языка.
Когда вы запускаете код с такой ошибкой, интерпретатор JavaScript — та штука, которая исполняет JavaScript-программы — пожалуется: SyntaxError и укажет вам на то место, где по его мнению есть проблема.
const cube = (num) => {
return num * num * num;
})
→ node test.js
/Users/rakhim/test.js:3
})
^
SyntaxError: Unexpected token )
at Object.exports.runInThisContext (vm.js:78:16)
at Module._compile (module.js:543:28)
at Object.Module._extensions..js (module.js:580:10)
at Module.load (module.js:488:32)
at tryModuleLoad (module.js:447:12)
at Function.Module._load (module.js:439:3)
at Module.runMain (module.js:605:10)
at run (bootstrap_node.js:420:7)
at startup (bootstrap_node.js:139:9)
at bootstrap_node.js:535:3
Вот, например, это определение функции и в конце — лишняя скобка. Её там быть не должно и это ломает всю программу, поэтому JavaScript жалуется: “SyntaxError:” Unexpected token (символ))”. Эта скобка unexpected — неожиданная.
Синтаксическая ошибка — это как если кто-то бредит вслух. Никто вокруг ничего не понимает.
Следующий тип ошибки подобен синтаксической, но в этом случае вы нарушаете не законы синтаксиса языка, а как бы законы синтаксиса собственного кода. В прошлый раз мы создали функцию abs
, которая возвращала абсолютное значение числа.
→ node test.js
/Users/rakhim/test.js:1
ads(12);
^
ReferenceError: ads is not defined
at Object.<anonymous> (/Users/rakhim/test.js:1:63)
at Module._compile (module.js:571:32)
at Object.Module._extensions..js (module.js:580:10)
at Module.load (module.js:488:32)
at tryModuleLoad (module.js:447:12)
at Function.Module._load (module.js:439:3)
at Module.runMain (module.js:605:10)
at run (bootstrap_node.js:420:7)
at startup (bootstrap_node.js:139:9)
at bootstrap_node.js:535:3
Если вы вызовете ads
вместо abs
, интерпретатор JavaScript пожалуется: ReferenceError: ads is not defined
. Вы использовали, как вам кажется, существующее название, но на самом деле такого названия нет.
Несколько строк, которые следуют после указания ошибки, могут смутить и оттолкнуть вас, но они тут только для пользы. Это stack trace — последовательность вызовов функций, которая привела к ошибке. Когда вы запускаете свою программу, даже крошечную, она становится частью чего-то более крупного — сложной системой JavaScript-кода, который приводится в действие, чтобы оживить вашу программу. Тут видно, что проблема была в моём файле. Следующая строка — это место, откуда был вызван мой код, третья строка — откуда была вызвана вторая и в таком духе можно продолжать дальше. Это как отслеживать шаги в обратном направлении — проблема есть, и мы можем возвращаться по одному шагу назад и смотреть, не нашлась ли ошибка.
Мы допускаем, что вся внутренняя система исправно работает, поэтому ошибка в нашем коде. Когда одна из ваших функций вызывает другую, вы увидите эту последовательность вызовов в стектрейсе.
ReferenceError может случиться с другими константами: например, если ваш код содержит 10 * pi
, а pi
не существует, потому что вы не создавали константу с точно таким названием, вы получите ReferenceError.
ReferenceError — это как называть кого-то чужим именем.
Следующий тип ошибки — когда вы путаете одну вещь с другой. Взгляните на этот код:
const length = 12;
const num = length(54);
Сначала мы создали константу. Помните, что это как давать чему-то название: в нашем случае — числу 12 даётся название length
. В следующей строке мы вызываем функцию length
и передаём ей аргумент — число 54. Но подождите! length
— это не функция! Это всего лишь число. Числа — это не функции, не ящики, которые производят какие-то действия. И JavaScript пожалуется именно на это:
→ node test.js
/Users/rakhim/test.js:2
const num = length(-54);
^
TypeError: length is not a function
at Object.<anonymous> (/Users/rakhim/test.js:2:13)
at Module._compile (module.js:571:32)
at Object.Module._extensions..js (module.js:580:10)
at Module.load (module.js:488:32)
at tryModuleLoad (module.js:447:12)
at Function.Module._load (module.js:439:3)
at Module.runMain (module.js:605:10)
at run (bootstrap_node.js:420:7)
at startup (bootstrap_node.js:139:9)
at bootstrap_node.js:535:3
Это Ошибка типизации: тип объекта, который вы использовали, неверный. Интерпретатор JavaScript не скажет чем что-то является, но точно скажет чем оно не является. length
— это не функция.
Ошибка типизации — это как просить кошку постирать бельё. Возможно, вы хотели попросить об этом вашего друга.
Все эти ошибки — syntax error, reference error и type error — возникают из-за использования неправильных слов. И все они предельно очевидные: вы видите сообщение об ошибке и достаточно хорошо понимаете в чём проблема. Обычно сразу понятно, как их исправить:
- Синтаксическая ошибка? Заменить, удалить или добавить символы. Часто проблема в скобках и кавычках: открытые скобки и открытые кавычки должны быть закрыты.
- Reference error? Проверить, существует ли тот объект, на который вы ссылаетесь. Возможно, вы использовали неправильное название или забыли создать его.
- Ошибка типизации? Убедиться, что вы используете объекты верно. Часто проблема — простая путаница: вы создали и числовую константу и функцию, а потом пытаетесь вызвать число. Наверное, вы хотели вызвать функцию.
Последний тип ошибки, о котором мы сегодня поговорим — самый злой: Логическая ошибка. Допустим, мы пишем функцию, которая конвертирует градусы по фаренгейту (F) в градусы по цельсию (C). Чтобы сконвертировать температуру по одной шкале в другую, нужно вычесть 32 и умножить на 5/9. Например (50°F – 32) x 5/9 = 10°C.
const fahrToCelsius = (fahr) => {
return fahr - 32 * 5/9;
}
Выглядит нормально? Давайте запустим эту функцию, сконвертируем 50 градусов и выведем на экран:
console.log(fahrToCelsius(50));
И у нас получилось 32.22222222222222. Не 10. Что произошло? JavaScript не пожаловался, когда код запустился, никаких ошибок не выскакивало. Компьютер не знает, что нам нужно, поэтому он производит вычисление, как мы его и просили. Но такое вычисление ошибочно — допустили ошибку мы. Нам нужно вначале вычесть 32, а потом умножить это на 5/9. Но мы не использовали скобки, поэтому 32 вначале умножилось на 5/9, а затем результат был отнят от температуры в фаренгейтах.
Это Логическая ошибка. Мы не нарушили никаких правил, мы просто сделали что-то не то. Наш пример был простым: мы написали функцию, запустили её и увидели неверный результат. Но представьте, что функция — это только маленькая частица крупной системы. Приложение для формирования бюджета в огромной организации отправляет отчёт в главную бухгалтерию, что в следующем месяце для оплаты счёта за электричество требуются дополнительные $300 000. Организуется экстренное собрание, увольняют людей, генеральный директор снова уходит в запой. Что случилось?
Иногда обнаружить проблему может оказаться трудной задачей: система кондиционирования ожидает, что январская температура будет 32 градуса по цельсию, вместо 10, потому что кто-то забыл использовать скобки в функции.
Борьба с логическими ошибками — это целиком ваша ответственность. И временами — тяжёлая работа, но в конце приходит сильное облегчение и удовлетворение: а-ааа, так вот в чём была проблема!
Теперь ваша очередь делать ошибки! Выполните тест и упражнение, чтобы ощутить боль.
Дополнение к уроку
Листочек
Самый действенный способ понять, как работает участок кода —
это расписать его выполнение на бумажке, как если бы вы были компьютером (медленным и немного голодным).
Метод утенка
Метод утёнка — психологический метод решения задачи, делегирующий её мысленному помощнику. Метод описан в книге «Программист-прагматик».
Тестируемый ставит на рабочем столе игрушечного утёнка
(или представляет его мысленно; на самом деле уточка – это условно, предмет может быть любым), и когда у него возникает вопрос, на который трудно ответить, то он задаёт его игрушке, как живому человеку, словно она действительно может ответить.
Считается, что правильная формулировка вопроса содержит как минимум половину ответа, а также это дает толчок мыслям, направляя их в нужное русло.
Метод также используется при отладке. Если определённая часть программы не работает, программист пытается объяснить утёнку, что делает каждая строка программы, и в процессе этого сам находит ошибку.
Выводы
4 типа ошибок:
- Syntax error. Неверное использование языка. Часто лишние или недостающие скобки или кавычки. Что делать? Заменить, удалить или добавить символы. Часто проблема в скобках или кавычках: открытые скобки должны быть закрыты, открытые кавычки должны быть закрыты.
- Reference error. Использование несуществующего названия. Что делать? Проверить, существует ли то, на что вы ссылаетесь. Возможно вы использовали ошибочное название или забыли его создать.
- Type error. Использование неверного типа, например попытка вызвать константу числа, как функцию. Что делать? Убедиться, что всё используется верно. Часто проблема в простой путанице: вы создали численную константу и функциональную константу, а потом пытаетесь вызвать число. Вероятно вы собирались вызвать функцию.
- Logic error. (Логическая ошибка) Ваш код выполняет не то, что требуется, но программа запускается и не выдаёт ошибок трёх перечисленных выше типов. Сломана логика. Что делать? Проверить свой код, убедиться, что он выполняет то, что должен.
Остались вопросы? Задайте их в разделе «Обсуждение»
Вам ответят команда поддержки Хекслета или другие студенты.