В материале рассматриваются примеры отличия сообщений об ошибках в Python 3.10 от более ранних версий. Улучшения коснулись сообщений об ошибках, таких как SyntaxErrors
, IndentationErrors
, AttributeErrors
и NameErrors
.
SyntaxErrors
;IndentationErrors
;AttributeErrors
;NameErrors
.SyntaxErrors
.При синтаксическом анализе кода, который содержит незакрытые скобки, с версии Python 3.10, вместо отображения сообщения SyntaxError: unexpected EOF
и указание на какое-то неправильное место, интерпретатор включает местоположение незакрытых скобок. Например, рассмотрим следующий код (обратите внимание на незакрытый '{'
):
expected = {9: 1, 18: 2, 19: 2, 27: 3, 28: 3, 29: 3, 36: 4, 37: 4, 38: 4, 39: 4, 45: 5, 46: 5, 47: 5, 48: 5, 49: 5, 54: 6, some_other_code = foo()
Предыдущие версии интерпретатора сообщали о запутанных местах в качестве места синтаксической ошибки:
File "example.py", line 3 some_other_code = foo() ^ SyntaxError: invalid syntax
но в Python 3.10 выдается более информативная ошибка:
File "example.py", line 1 expected = {9: 1, 18: 2, 19: 2, 27: 3, 28: 3, 29: 3, 36: 4, 37: 4, ^ SyntaxError: '{' was never closed
Точно так же ошибки, связанные с незакрытыми строковыми литералами (одинарными и тройными кавычками), теперь указывают на начало строки вместо сообщения EOF/EOL
.
Эти улучшения вдохновлены предыдущей работой в интерпретаторе PyPy.
Исключения SyntaxError
, вызванные интерпретатором, теперь будут выделять полный диапазон ошибок выражения, составляющего саму синтаксическую ошибку, а не только то место, где обнаружена проблема. Таким образом, вместо отображения (до Python 3.10):
>>> foo(x, z for z in range(10), t, w) # File "<stdin>", line 1 # foo(x, z for z in range(10), t, w) # ^ # SyntaxError: Generator expression must be parenthesized
теперь Python 3.10 отобразит исключение как:
>>> foo(x, z for z in range(10), t, w) # File "<stdin>", line 1 # foo(x, z for z in range(10), t, w) # ^^^^^^^^^^^^^^^^^^^^ # SyntaxError: Generator expression must be parenthesized
SyntaxError
.Для исключений SyntaxError
добавлено значительное количество новых специализированных сообщений. Вот некоторые из наиболее примечательных:
:
перед блоком:>>> if rocket.position > event_horizon # File "<stdin>", line 1 # if rocket.position > event_horizon # ^ # SyntaxError: expected ':'
>>> {x,y for x,y in zip('abcd', '1234')} # File "<stdin>", line 1 # {x,y for x,y in zip('abcd', '1234')} # ^ # SyntaxError: did you forget parentheses around the comprehension target?
>>> items = { ... x: 1, ... y: 2 ... z: 3, # File "<stdin>", line 3 # y: 2 # ^ # SyntaxError: invalid syntax. Perhaps you forgot a comma?
>>> try: ... build_dyson_sphere() ... except NotEnoughScienceError, NotEnoughResourcesError: # File "<stdin>", line 3 # except NotEnoughScienceError, NotEnoughResourcesError: # ^ # SyntaxError: multiple exception types must be parenthesized
:
и/или значение ключа в словарях:>>> values = { ... x: 1, ... y: 2, ... z: ... } # File "<stdin>", line 4 # z: # ^ # SyntaxError: expression expected after dictionary key and ':' >>> values = {x:1, y:2, z w:3} # File "<stdin>", line 1 # values = {x:1, y:2, z w:3} # ^ # SyntaxError: ':' expected after dictionary key
try
без except
или finally
:>>> try: ... x = 2 ... something = 3 # File "<stdin>", line 3 # something = 3 # ^^^^^^^^^ # SyntaxError: expected 'except' or 'finally' block
=
вместо ==
при сравнении:>>> if rocket.position = event_horizon: # File "<stdin>", line 1 # if rocket.position = event_horizon: # ^ # SyntaxError: cannot assign to attribute here. # Maybe you meant '==' instead of '='?
*
в f-строках:>>> f"Black holes {*all_black_holes} and revelations" # File "<stdin>", line 1 # (*all_black_holes) # ^ # SyntaxError: f-string: cannot use starred expression here
IndentationErrors
.Многие исключения IndentationError
теперь имеют больше контекста относительно того, какой блок ожидает отступ, включая расположение оператора:
>>> def foo(): ... if lel: ... x = 2 # File "<stdin>", line 3 # x = 2 # ^ # IndentationError: expected an indented block after 'if' statement in line 2
AttributeErrors
.При печати исключения AttributeError
, функция интерпретатора PyErr_Display()
предложит варианты похожих имен атрибутов в объекте, из которого возникло исключение:
>>> collections.namedtoplo # Traceback (most recent call last): # File "<stdin>", line 1, in <module> # AttributeError: module 'collections' has no attribute 'namedtoplo'. # Did you mean: namedtuple?
Предупреждение. Обратите внимание, что это не сработает, если для отображения ошибки не вызывается `PyErr_Display(). Это может произойти при использовании какой-либо другой пользовательской функции отображения ошибок. Например, это распространенный сценарий в IPython.
NameErrors
.При печати исключения NameError
, функция интерпретатора PyErr_Display()
предложит варианты похожих имен переменных в функции, из которой было вызвано исключение:
>>> schwarzschild_black_hole = None >>> schwarschild_black_hole # Traceback (most recent call last): # File "<stdin>", line 1, in <module> # NameError: name 'schwarschild_black_hole' is not defined. Did you mean: schwarzschild_black_hole?
Предупреждение. Обратите внимание, что это не сработает, если для отображения ошибки не вызывается `PyErr_Display(). Это может произойти при использовании какой-либо другой пользовательской функции отображения ошибок. Например, это распространенный сценарий в IPython.