Голое SyntaxError: invalid syntax без пояснения почти всегда значит, что сломана строка выше той, что назвал Python. А если после двоеточия есть подсказка, правьте ровно то место, куда показывает каретка, и никуда больше.
Вы запустили файл, вместо программы три строки красного текста, открываете указанную строку, а она выглядит нормально. Ниже шесть причин, которые дают почти все такие ошибки. Сообщения сняты с реального запуска Python 3.13.0: с версии 3.10 они изменились, и половина ответов в поиске описывает текст, которого у вас на экране нет.
Читайте текст после двоеточия
expected ':' и Perhaps you forgot a comma? называют причину прямо и указывают на верное место.
Голое invalid syntax значит строку выше
Парсер сдался там, где перестал понимать код, а опечатка осталась позади.
Каретка важнее номера строки
Символы ^ отмечают точный фрагмент, соседний код не трогайте.

Почему Python показывает не ту строку?
Парсер сообщает не место опечатки, а координату, на которой конструкция перестала складываться. Пропущенная запятая в конце строки ещё не ошибка: следующим символом мог быть перенос внутри скобок. Ошибкой она становится строкой ниже, туда Python и ставит указатель.
user = {
"name": "Аня"
"age": 20,
}
# python3 -m py_compile app.py
File "app.py", line 3
"age": 20,
^
SyntaxError: invalid syntaxСтрока 3 написана правильно, запятая забыта на строке 2, после "Аня". Пояснения после двоеточия нет, значит правило работает: поднимитесь на строку вверх и проверьте её конец.
Причины 1-3: двоеточие, скобка, одно равно
Эти три Python 3.13 распознаёт сам: номер строки верный, искать ничего не нужно.
# было
age = 20
if age >= 18
print("совершеннолетний")
File "app.py", line 2
if age >= 18
^
SyntaxError: expected ':'
# стало
if age >= 18:Двоеточие требуют if, elif, else, for, while, def, class, try, except, with. Причина 2 ведёт себя иначе.
# было
total = sum([1, 2, 3]
print(total)
File "app.py", line 1
total = sum([1, 2, 3]
^
SyntaxError: '(' was never closed
# было
name = "Аня
print(name)
File "app.py", line 1
name = "Аня
^
SyntaxError: unterminated string literal (detected at line 1)Почему поиск в интернете сбивает с толку
В Python 3.10, вышедшем в октябре 2021 года, незакрытая скобка перестала выдавать unexpected EOF while parsing где-то в конце файла и стала выдавать '(' was never closed с указателем на саму скобку, а в 3.11 каретки ^ добавили и в обычные трассировки (PEP 657). Ответы старше 2021 года описывают сообщение, которого у вас уже нет.
Третья причина, одно равно вместо двух: одно кладёт значение в переменную, два спрашивают, совпадают ли значения.
# было
x = 10
if x = 10:
print("десять")
File "app.py", line 2
if x = 10:
^^^^^^
SyntaxError: invalid syntax. Maybe you meant '==' or ':=' instead of '='?
# стало
if x == 10:Вы точно в этой ситуации, если каретка накрыла x = 10 целиком, а не один символ. Python подчёркивает выражение, которое не может стоять внутри условия.
Причины 4-6: запятая, print из прошлого, занятое имя
Четвёртая причина, пропущенная запятая, живёт в двух видах.
# было
def add(a, b):
return a + b
print(add(2 3))
File "app.py", line 4
print(add(2 3))
^^^
SyntaxError: invalid syntax. Perhaps you forgot a comma?
# стало
print(add(2, 3))Разнесите те же аргументы на две строки, и подсказка пропадёт: останется голое invalid syntax с указателем на вторую строку. Причина 5 наоборот, самая говорящая.
# было
print "Привет, мир"
File "app.py", line 1
print "Привет, мир"
^^^^^^^^^^^^^^^^^^^
SyntaxError: Missing parentheses in call to 'print'. Did you mean print(...)?
# стало
print("Привет, мир")В Python 2 print был инструкцией языка и скобок не требовал, значит вы копируете код из учебника старше 2008 года. Шестая причина, недопустимое имя: в Python 3.13 занято 35 слов языка плюс два правила на форму имени.
Строка | Работает | Что не так |
|---|---|---|
| нет |
|
| нет |
|
| нет | дефис читается как минус, выходит вычитание |
| да | подчёркивание в конце снимает конфликт со словом языка |
| да | цифра разрешена везде, кроме первого символа |
Про дефис Python пишет cannot assign to expression here: он видит вычитание и жалуется на присваивание, а не на имя.
Найти синтаксическую ошибку за минуту
Слева текст после SyntaxError:, справа что открыть в редакторе.
Сообщение | Куда смотреть |
|---|---|
| конец указанной строки, добавьте двоеточие |
| на саму скобку, поломка может быть на 20 строк ниже |
| кавычки по краям строки, их нечётное число |
| условие внутри |
| промежуток между фрагментами под кареткой |
| обернуть аргумент в скобки |
| первый символ имени переменной |
| конец предыдущей строки |
Шесть шагов по порядку
Прочитайте текст справа от
SyntaxError:. Есть пояснение, идите в таблицу выше и правьте под кареткой.Пояснения нет, только
invalid syntax. Откройте строку с номером из сообщения и поднимитесь на строку вверх.Проверьте конец этой строки на четыре вещи: двоеточие, закрывающая скобка, закрывающая кавычка, запятая.
Поставьте курсор рядом с каждой открывающей скобкой: редактор подсветит парную, непарная останется без подсветки.
Проверьте правку, не запуская программу:
python3 -m py_compile app.py, файл разбирается, но не выполняется.Повторите с первого шага: Python показывает одну ошибку за раз.
Признак, что этап пройден
py_compile отработал молча и ничего не напечатал. Пустой вывод и есть успех: синтаксис чистый, дальше пойдут ошибки времени выполнения с другими именами.
Промахи, из-за которых поиск затягивается
Править строку, которую назвал Python
При голом invalid syntax она обычно безупречна: вы сломаете здоровый код, пока опечатка ждёт строкой выше.
Искать в интернете дословный текст ошибки
Ответы про unexpected EOF while parsing написаны до октября 2021 года и к вашей версии не подходят.
Чинить всё найденное разом
Парсер остановился на первой ошибке, остальные правки вы делаете вслепую и добавляете новые опечатки.
Путать SyntaxError с NameError
SyntaxError падает до запуска. Если программа успела что-то напечатать, синтаксис тут ни при чём.
Считать скобки глазами
На print(sum(len(x))) счёт сбивается на третьем уровне, а подсветка пары в редакторе отвечает сразу.
Короткая проверка себя назовите вслух, что выдаст for i in range(3) без двоеточия. Ответили expected ':', значит вы читаете ошибки, а не гадаете.
Как это устроено в Кодике?
Разбирать чужие сообщения полезно, но быстрее учиться на своих. В Кодике код пишется и запускается прямо в телефоне: пропустили двоеточие, нажали запуск, увидели expected ':' через секунду и поправили. Цикл в пару секунд ставит привычку читать текст ошибки надёжнее любой таблицы.
А ещё у нас тёплое и дружеское комьюнити в telegram, где каждый может задать вопрос и получить ответ — без осуждения и лишней теории. Мы вместе решаем задачи, разбираем ошибки и поддерживаем друг друга на пути к цели.
