Если исходный код Python скомпилирован в байт-код перед интерпретацией / JITing, почему эта ошибка не обнаруживается до выполнения? - PullRequest
0 голосов
/ 20 ноября 2018

Я написал следующую функцию:

def f():
    for i in range(100000):
        print(i)
    some_function_that_doesnt_exist()

Когда я запускаю свой файл, он напечатает числа в диапазоне 100000, а затем выдаст ошибку: NameError: name 'some_function_that_doesnt_exist' is not defined.

Это пример более широкого вопроса, который у меня есть по поводу Python.Если код Python скомпилирован в байт-код до того, как виртуальная машина Python его интерпретирует (или JIT), почему мы не видим эту ошибку во время компиляции?Почему распечатывается 100000 номеров, прежде чем мы наконец увидим ошибку?В чисто скомпилированном языке, таком как C, мы увидим ошибку во время компиляции, так почему бы нам не увидеть ее на этом «частично скомпилированном» языке?

Ответы [ 2 ]

0 голосов
/ 20 ноября 2018

Вы можете посмотреть, что запускает виртуальная машина Python, используя dis:

import dis

def f():
    for i in range(100000):
        print(i)
    some_function_that_doesnt_exist()


dis.dis(f)

Будет выводить:

  4           0 SETUP_LOOP              24 (to 26)
              2 LOAD_GLOBAL              0 (range)
              4 LOAD_CONST               1 (100000)
              6 CALL_FUNCTION            1
              8 GET_ITER
        >>   10 FOR_ITER                12 (to 24)
             12 STORE_FAST               0 (i)

  5          14 LOAD_GLOBAL              1 (print)
             16 LOAD_FAST                0 (i)
             18 CALL_FUNCTION            1
             20 POP_TOP
             22 JUMP_ABSOLUTE           10
        >>   24 POP_BLOCK

  6     >>   26 LOAD_GLOBAL              2 (some_function_that_doesnt_exist)
             28 CALL_FUNCTION            0
             30 POP_TOP
             32 LOAD_CONST               0 (None)
             34 RETURN_VALUE

Это то, что на самом деле работает виртуальная машина Python.как вы можете видеть из строк с 10 по 24, на самом деле речь идет о печати.
Только когда вы достигнете строки 26, ВМ Python пытается загрузить функцию, что приводит к ошибке имени.



Немного по-разному, когда компилируемый язык выполняет компиляциюДля байт-кода (например, от C до сборки), вызов функции должен точно знать, где в памяти находится функция.Таким образом, когда вы пытаетесь скомпилировать несуществующую функцию, она не сможет преобразовать ее в байт-код, так как не сможет найти местоположение функции.
Python VM может получить доступ к массиву глобальных переменных, которые могутможет быть изменено в реальном времени, и поиск в этом массиве также в реальном времени.
Выполнение:

dis.dis("def some_function_that_doesnt_exist(): 1")

приведет к:

  1           0 LOAD_CONST               0 (<code object some_function_that_doesnt_exist at 0x7f38dc90ed20, file "<dis>", line 1>)
              2 LOAD_CONST               1 ('some_function_that_doesnt_exist')
              4 MAKE_FUNCTION            0
              6 STORE_NAME               0 (some_function_that_doesnt_exist)
              8 LOAD_CONST               2 (None)
             10 RETURN_VALUE

Где строка 2 загружаетимя функции из таблицы const и после создания функции в строке 4 сохраняет ее в соответствии с именем в строке 6. Таким образом, при поиске этой функции в следующий раз, Python VM сможет найти ее.

0 голосов
/ 20 ноября 2018

Python-код компилируется в байт-код, и этот байт-код интерпретируется во время выполнения.Ваш код является корректным Python, поэтому он успешно скомпилируется в байт-код.Однако этот байт-код выдаст ошибку во время выполнения, когда интерпретатор попытается его выполнить.

...