Является ли перевод в байт-код в python построчным?
Имеется код:
try:
def f():
print('hi')
print('bye) # здесь намеренно пропущен закрывающий апостроф
except:
pass
f()
Целью эксперимента было: выяснить, что произойдёт при вызове функции f, построчное определение (def) которой в run-time провалилось. Предполагалось, что определение (def) как оператор провалилось, поэтому объект функции и ссылка f на него не создадутся в глобальной области видимости модуля. Поэтому предполагалось, что вызов f() приведёт к возбуждению исключения NameError.
В действительности оказалось, что при запуске выходит SyntaxError, и строка 'hi' не печатается. Думаю, что то ли блок try не ловит исключение, то ли bite-code всего модуля не смог создаться, а потому не выполнился его запуск в принципе, и оператор def даже не начинал работу (собственно как и последующий оператор вызова f()).
Вопрос: Помогите, пожалуйста, разобраться, почему до вызова f() дело не дошло. Возможно одно из моих предположений выше верно, тогда хотелось бы увидеть ссылки на документацию, подробно объясняющие происходящее.
Ответ:
Сначала исходник проходит фазу токенизации. Потом из токенов строится AST. Потом компилятор транслирует AST в байткод. Полученный байткод выполняет PVM. Перехват исключений, очевидно, может работать только в процессе выполнения байткода виртуальной машиной, на предыдущих этапах самого механизма исключений ещё не существует, поэтому SyntaxError перехватить нельзя. Конечно, если исключить варианты с парсингом в рантайме, типа выполнения инструкции eval.