Python во многом снисходителен, но только не его синтаксический анализатор. SyntaxError останавливает программу ещё до того, как выполнится хотя бы одна строка, что особенно обидно, когда исправление сводится к одному пропущенному символу. Хорошая новость: одни и те же ошибки составляют почти весь спектр синтаксических проблем, с которыми вы когда-либо столкнётесь, и научившись узнавать их с первого взгляда, вы будете исправлять их за секунды.
Это руководство разбирает наиболее распространённые синтаксические ошибки Python, а также тесно связанные с ними случаи IndentationError, TabError и NameError, которые сбивают людей с толку по тем же причинам. В каждом разделе приведён некорректный фрагмент кода, сообщение об ошибке, которое выводит Python, и исправленный вариант. Все фрагменты настоящие и готовы к копированию, так что вы можете воспроизвести ошибку и убедиться в правильности исправления в своём интерпретаторе.
Что такое синтаксическая ошибка в Python?
Синтаксическая ошибка означает, что ваш код нарушает грамматику языка, поэтому интерпретатор не может разобрать его в нечто исполняемое. Поскольку разбор происходит до выполнения, программа никогда не запускается: ничего не печатается, никаких побочных эффектов не возникает, вы просто получаете трассировку, которая завершается SyntaxError с указателем на проблемный токен или сразу после него.
Вот классический пример: вызов без закрывающей скобки.
print("Hello, Python!"
Python достигает конца файла, всё ещё ожидая ), которая закрывает вызов, поэтому он сообщает о проблеме в конце входных данных.
SyntaxError: '(' was never closed
Важно скорректировать своё понимание на раннем этапе: синтаксическая ошибка не то же самое, что ошибка времени выполнения. Синтаксические ошибки перехватываются на этапе разбора и не дают программе вообще запуститься. Ошибки времени выполнения (деление на ноль, открытие несуществующего файла) возникают в процессе исполнения синтаксически корректной программы. Это руководство посвящено первому виду ошибок, тем, которые не позволяют вашему коду запуститься в принципе.
Распространённые синтаксические ошибки Python и способы их исправления
Разделы ниже расположены примерно в том порядке, в котором вы, скорее всего, будете встречать эти ошибки. Каждый раздел самодостаточен, поэтому смело переходите сразу к тому сообщению об ошибке, которое сейчас перед вами.
1. Отсутствующие или несоответствующие скобки
Скобки группируют выражения и вызывают функции, и они должны быть сбалансированы. Незакрытая открывающая скобка, одна из самых распространённых синтаксических ошибок, особенно в длинных условиях, где закрывающую скобку легко упустить.
if (x > 10: print("x is greater than 10")
Python ожидает закрывающую скобку перед двоеточием и сообщает об этом.
SyntaxError: closing parenthesis ':' does not match opening parenthesis '('
Исправление: убедитесь, что у каждой открывающей скобки есть соответствующая закрывающая того же вида. Поставьте скобку перед двоеточием, и условие разберётся без ошибок. То же правило действует для квадратных скобок [] и фигурных {}; редакторы с подсветкой парных скобок улавливают большинство таких ошибок за вас.
if (x > 10): print("x is greater than 10")
2. Отсутствующее двоеточие в управляющей конструкции
Каждый заголовок составной инструкции в Python заканчивается двоеточием: if, elif, else, for, while, def, class, try и все остальные. Пропуск двоеточия, классическая ошибка тех, кто переходит с языка с фигурными скобками.
if x > 5 print("x is greater than 5")
Современный Python указывает прямо на пропущенный токен.
SyntaxError: expected ':'
Добавьте двоеточие в конец строки заголовка. Каждый раз, когда вы пишете инструкцию, открывающую новый блок с отступом, взгляд должен автоматически проверять наличие завершающего двоеточия.
if x > 5: print("x is greater than 5")
3. Ожидался блок с отступом (IndentationError)
Python использует отступы вместо фигурных скобок для обозначения блоков кода, поэтому тело каждого if, цикла или функции должно иметь отступ. Напишите заголовок с двоеточием, а затем забудьте сделать отступ в следующей строке, и анализатор не найдёт блока, к которому можно привязать выполнение.
for i in range(5): print(i)
Интерпретатор сообщает, что после заголовка цикла ожидался блок с отступом.
IndentationError: expected an indented block after 'for' statement on line 1
Сделайте отступ тела в четыре пробела, согласно стандартному соглашению Python. Отступ здесь является синтаксисом, а не стилистическим предпочтением: именно так Python понимает, какие строки принадлежат циклу.
for i in range(5): print(i)
4. Неожиданный отступ (IndentationError)
Обратная ошибка: отступ в строке, которая должна находиться на том же уровне, что и соседние строки. Отступы внутри блока должны быть согласованными, поэтому один лишний пробел или два на одной строке ломают разбор.
def example(): print("First line") print("Second line")
Второй print имеет больший отступ, чем первый, без какой-либо причины, и Python отклоняет это.
IndentationError: unexpected indent
Выровняйте все инструкции одного блока по одному столбцу. Выберите четыре пробела на уровень и придерживайтесь этого, и функция автоотступа редактора, как правило, будет поддерживать порядок за вас.
def example(): print("First line") print("Second line")
5. Смешивание табуляции и пробелов (TabError)
Особенно коварная ошибка отступа, смешивание табуляции и пробелов в одном блоке. Они могут выглядеть одинаково на экране, но Python обрабатывает их по-разному и выбрасывает специальный TabError. В приведённом ниже фрагменте первая строка тела использует пробелы, а вторая, табуляцию.
def greet(name): message = "Hi " + name return message
Несмотря на то что обе строки визуально выравниваются, Python не может определить, находятся ли они на одном уровне.
TabError: inconsistent use of tabs and spaces in indentation
Остановитесь на пробелах, как рекомендует PEP 8, и никогда не смешивайте. Настройте редактор на вставку пробелов при нажатии Tab и выполните поиск с заменой в любом файле, где уже есть смесь. Переформатирование обеих строк тела с четырьмя пробелами устранит ошибку.
Ошибки из-за табуляции против пробелов невидимы, пока вы не включите отображение пробельных символов. В большинстве редакторов есть переключатель «показать пробелы» или «отображать управляющие символы», который рисует табуляцию и пробелы как отличные друг от друга знаки. Включите его однажды, и эти ошибки перестанут быть загадочными.
6. EOL при сканировании строкового литерала
Строка должна открываться и закрываться в одной строке кода с совпадающими кавычками. Забудьте закрывающую кавычку или закройте другим видом кавычек, и Python дойдёт до конца строки, всё ещё находясь внутри строки.
name = 'John"
Строка открывается одинарной кавычкой, но закрывается двойной, поэтому она никогда не завершается.
SyntaxError: unterminated string literal (detected at line 1)
Используйте один и тот же символ кавычки с обоих концов. Если текст содержит кавычку, оберните строку другим видом кавычек, например "O'Brien", или используйте тройные кавычки для текста, который занимает несколько строк. В более старых версиях Python та же ошибка формулируется как EOL while scanning string literal, но причина идентична.
name = 'John'
7. EOF при сканировании (неожиданный конец файла)
Тесно связана с предыдущей ошибка конца файла: открывающая скобка или кавычка, которая так и не закрывается до конца файла. Это и есть рассмотренный ранее случай незакрытого вызова, и он заслуживает отдельного раздела, поскольку сообщение об ошибке называет иную причину. Обычный виновник, многострочная конструкция с пропущенным закрывающим элементом.
numbers = [1, 2, 3 print(sum(numbers))
Поскольку список никогда не закрывается, Python продолжает читать, воспринимает следующую строку как часть списка и выходит за конец файла.
SyntaxError: '[' was never closed
Закройте скобку там, где заканчивается конструкция. Если ошибка указывает на самый конец файла, реальная проблема почти всегда заключается в незакрытой открывающей скобке несколькими строками выше, поэтому ищите вверх от указателя.
numbers = [1, 2, 3] print(sum(numbers))
8. Неверное присваивание: = против ==
Одиночный = присваивает значение, двойной == сравнивает два значения. Используйте присваивание там, где должно быть сравнение, например в условии if, и Python отклонит это, поскольку в обычном условном тесте нельзя выполнять присваивание.
if x = 10: print("x is 10")
Последние версии Python прямо говорят, что вы, вероятно, имели в виду.
SyntaxError: invalid syntax. Maybe you meant '==' or ':=' instead of '='?
Используйте == для сравнения, а = оставьте для присваивания. Если вам действительно нужно выполнить присваивание в составе выражения, для этого предназначен оператор моржа :=, но для обычного условия вы почти всегда имеете в виду ==.
if x == 10: print("x is 10")
Когда ваш синтаксический анализатор работает корректно, главная сложность в парсере, это сам запрос: рендеринг JavaScript-страниц и ротация IP, чтобы вас не заблокировали. Crawling API решает обе задачи за один запрос и возвращает готовый HTML, поэтому ваш безошибочный код на Python занимается обработкой данных, а не борьбой с парком headless-браузеров и пулом прокси.
9. Использование зарезервированного ключевого слова в качестве имени
Python резервирует слова вроде for, if, class, return и import для самого языка. Попытайтесь использовать одно из них как имя переменной, и анализатор увидит ключевое слово там, где ожидает идентификатор.
for = 10
Присваивание значения for недопустимо, потому что for может только начинать цикл.
SyntaxError: invalid syntax
Выберите имя, которое не является зарезервированным, в идеале описывающее хранимое значение. Если вы не уверены, занято ли имя, модуль keyword самого Python перечисляет все зарезервированные слова; проверка имени по keyword.kwlist моментально даст ответ.
import keyword num_for = 10 print("for" in keyword.kwlist) # True, so it is off limits
10. Пропущенные или неверно расставленные запятые
Запятые разделяют элементы в списках, кортежах, словарях и списках аргументов. Пропустите одну между двумя строковыми литералами, и Python попытается прочитать их как одно выражение, что недопустимо.
items = ["apple" "banana", "cherry"]
Python указывает на вторую строку, где ожидалась запятая.
SyntaxError: invalid syntax. Perhaps you forgot a comma?
Ставьте запятую между каждым элементом. Эта ошибка часто встречается потому, что Python молча конкатенирует два соседних строковых литерала: "apple" "banana" иногда разбирается без ошибки и даёт "applebanana", сбивающий с толку баг вместо очевидного отказа. Всегда явно разделяйте элементы запятыми.
items = ["apple", "banana", "cherry"]
11. Некорректные инструкции импорта
У импортов своя грамматика. Забудьте указать, что именно импортируете, и форма from ... import останется незавершённой.
from math import
Анализатор достигает конца строки, всё ещё ожидая имени для импорта.
SyntaxError: invalid syntax
Укажите, что именно импортируете, или импортируйте весь модуль. Оба варианта ниже допустимы: импортируйте модуль и обращайтесь к нему через точку либо извлекайте из него конкретные имена.
import os import sys from math import sqrt
12. print как инструкция вместо функции
В Python 2 print была инструкцией и писалась без скобок. В Python 3 это обычная функция, поэтому старая форма является синтаксической ошибкой. Это до сих пор сбивает с толку тех, кто копирует примеры из старых учебников.
print "Hello, Python!"
Python 3 даже предлагает исправление в сообщении.
SyntaxError: Missing parentheses in call to 'print'. Did you mean print(...)?
Заключите аргументы в скобки, как при вызове любой другой функции. То же самое касается exec, который тоже стал функцией в Python 3.
print("Hello, Python!")
13. NameError из-за опечатки
Последняя ошибка строго говоря не является синтаксической: код разбирается корректно, поэтому сбой происходит во время выполнения, а не на этапе разбора. Она включена сюда, поскольку её причина относится к тому же семейству мелких оплошностей, а исправление столь же быстрое. Опечатайтесь в имени переменной, и Python не найдёт её.
message = "hello" print(mesage)
Имя mesage никогда не было определено, поэтому Python выбрасывает NameError и услужливо угадывает, что вы имели в виду.
NameError: name 'mesage' is not defined. Did you mean: 'message'?
Исправьте написание, чтобы имя совпадало с его определением. Поскольку эта ошибка появляется только при фактическом выполнении строки, она может скрываться в ветке, которую вы редко задействуете, что является ещё одной причиной тестировать код небольшими фрагментами, а не весь сразу.
message = "hello" print(message)
Как избежать синтаксических ошибок Python
Полностью избавиться от этих ошибок не получится, но поймать почти все из них до запуска программы вполне реально. Несколько привычек делают большую часть работы.
- Используйте редактор с подсветкой синтаксиса. VS Code, PyCharm и даже лёгкие редакторы вроде Thonny подсвечивают несбалансированные скобки, некорректные отступы и незакрытые строки прямо в процессе набора, так что большинство ошибок не доходит до интерпретатора.
-
Выберите четыре пробела и никогда не смешивайте с табуляцией. Настройте редактор на вставку пробелов при нажатии Tab. Последовательные отступы сами по себе устраняют весь класс ошибок
IndentationErrorиTabError. - Используйте линтер. Инструменты Pylint, Flake8 и Ruff проверяют код на синтаксические проблемы, пропущенные запятые и неопределённые имена ещё до запуска, и большинство из них интегрируются прямо в редактор.
- Читайте сообщение об ошибке и указатель. Современный Python указывает на конкретный токен и нередко предлагает исправление. Номер строки, это место, где Python заметил проблему; для незакрытых скобок реальная причина обычно находится на одну-две строки выше.
- Тестируйте маленькими фрагментами. Запускайте несколько строк за раз, а не весь скрипт целиком. Ошибки гораздо проще обнаружить, когда виновниками могут быть лишь несколько новых строк.
Те же привычки поддерживают чистоту кода, когда вы переходите от учебных примеров к реальным проектам, в том числе к парсерам. Если вы хотите полноценное руководство о том, как применить рабочий Python на практике, смотрите статью как парсить сайты с помощью Python, а для обзора инструментов, к которым стоит обратиться, посмотрите лучшие библиотеки Python для веб-скрейпинга.
Ключевые выводы
- Синтаксические ошибки останавливают программу ещё до запуска. В отличие от ошибок времени выполнения, они перехватываются на этапе разбора, поэтому ничего не выполняется, пока вы их не устраните.
- Большинство синтаксических ошибок, пунктуационные. Пропущенное двоеточие, незакрытая скобка, несоответствующая кавычка или пропущенная запятая составляют подавляющее большинство случаев.
- Отступ, это синтаксис, а не стиль. Делайте отступы в телах блоков последовательно, используйте четыре пробела и никогда не смешивайте с табуляцией, это исключает весь класс ошибок IndentationError и TabError.
- = присваивает, а == сравнивает. Использование одного вместо другого, частая оплошность, на которую современный Python теперь указывает напрямую.
- Читайте сообщение и указатель. Последние версии Python называют конкретный токен и нередко предлагают исправление; для ошибок конца файла реальная причина обычно заключается в незакрытой открывающей скобке выше.
Часто задаваемые вопросы
В чём разница между синтаксической ошибкой и ошибкой времени выполнения в Python?
Синтаксическая ошибка нарушает грамматику языка, поэтому интерпретатор не может разобрать ваш код и программа никогда не запускается. Ошибка времени выполнения возникает в процессе выполнения корректной программы, когда операция завершается неудачей, например при делении на ноль или открытии несуществующего файла. Синтаксические ошибки перехватываются до выполнения, ошибки времени выполнения, во время него.
Почему Python так требователен к отступам?
Python использует отступы вместо фигурных скобок для определения блоков кода, что делает код читаемым и единообразным. Поскольку пробельные символы и есть синтаксис, непоследовательный отступ является настоящей ошибкой, а не придиркой к стилю. Придерживайтесь четырёх пробелов на уровень и позвольте редактору соблюдать это правило, и отступы перестанут быть источником багов.
Как исправить "SyntaxError: unexpected EOF while parsing"?
Это сообщение означает, что открывающая скобка, круглая скобка или кавычка так и не была закрыта, и Python вышел за конец файла, всё ещё ожидая закрывающего символа. Начните с строки, на которую указывает ошибка, и ищите вверх незакрытый открывающий символ. Более новые версии Python формулируют ту же проблему конкретнее, например '(' was never closed, что точно указывает на искомый символ.
Почему возникает TabError, хотя код визуально правильно отформатирован?
Потому что табуляция и пробелы могут выглядеть одинаково на экране, тогда как Python воспринимает их как разные символы. Если одна строка блока использует табуляцию, а другая, пробелы, отступы несогласованны, даже если они визуально выравниваются. Включите отображение пробельных символов в редакторе, конвертируйте всё в пробелы, и ошибка исчезнет.
Как обнаружить синтаксические ошибки до запуска кода?
Используйте редактор с подсветкой синтаксиса и линтер, например Pylint, Flake8 или Ruff. Они отмечают несбалансированные скобки, пропущенные запятые, плохие отступы и неопределённые имена прямо в процессе набора, так что большинство ошибок не доходит до интерпретатора. Тестирование небольших фрагментов кода также помогает изолировать любую ошибку, которая всё же проскользнёт.
print в Python, это функция или инструкция?
В Python 3 это функция, поэтому её нужно вызывать со скобками: print("text"). Форма print "text" без скобок была допустима только в Python 2 и теперь является синтаксической ошибкой. Если вы видите "Missing parentheses in call to print", значит вы читаете код в стиле Python 2 в интерпретаторе Python 3.
Обходите любой сайт в масштабе, без борьбы с инфраструктурой.
Crawlbase берёт на себя прокси, отпечатки и CAPTCHA, чтобы ваша команда выпускала конвейеры данных вместо поддержки обвязки краулинга. 1 000 запросов бесплатно, без карты.
