Как читать байт-код python?

мне очень сложно понять байт-код Python и его dis модуль.

import dis
def func():
   x = 1
dis.dis(func)

приведенный выше код при вводе интерпретатора выдает следующий вывод:

    0 LOAD_CONST                  1(1)
    3 STORE_FAST                  0(x)
    6 LOAD_CONST                  0(NONE)
    9 RETURN_VALUE

например:

что означает LOAD_CONST, STORE_FAST а цифры, как 0, 3, 6 и 9?

конкретный ресурс, где я могу найти эту информацию будет высоко ценится.

1 ответов


числа перед байт-кодами смещаются в исходные двоичные байт-коды:

>>> func.__code__.co_code
'd\x01\x00}\x00\x00d\x00\x00S'

некоторые байт-коды поставляются с дополнительной информацией (аргументами), которые влияют на то, как работает каждый байт-код, смещение говорит вам, в какой позиции в байт-потоке был найден байт-код.

на LOAD_CONST байт-код (ASCII d, hex 64) сопровождается двумя дополнительными байтами, кодирующими ссылку на константу, связанную с байт-кодом, например. В результате STORE_FAST код операции (ASCII }, hex 7D) находится в индексе 3.

на dis документацию списки что означает каждая инструкция. Для LOAD_CONST Он говорит:

запихивает co_consts[consti] в стек.

что относится к co_consts структура, которая всегда присутствует с объектом кода; компилятор создает это:

>>> func.__code__.co_consts
(None, 1)

код операции загружает индекс 1 из этой структуры (01 00 байт в байт-код кодирует a 1), и dis посмотрел это для вас; это значение 1.

следующая инструкция,STORE_FAST описано так:

магазины TOS в местном co_varnames[var_num].

здесь ТОС относится к верхней части стека; обратите внимание, что LOAD_CONST просто толкнул что-то на стеке,1 значение. co_varnames другая структура; она ссылается на имена локальных переменных, индекс ссылок на код операции 0:

>>> func.__code__.co_varnames
('x',)

dis тоже посмотрел, и имя, которое вы использовали в своем коде, -x. Таким образом, этот код операции хранится 1 на x.

еще один LOAD_CONST нагрузки None в стек из индекса 0, за которым следует RETURN_VALUE:

возвращает с TOS вызывающему объекту функции.

таким образом, эта инструкция занимает верхнюю часть стека (с None Constant) и возвращается из этого блока кода. None является возвращаемым значением по умолчанию для функций без явного return заявление.

вы что-то пропустили из dis выход, номера строк:

>>> dis.dis(func)
  2           0 LOAD_CONST               1 (1)
              3 STORE_FAST               0 (x)
              6 LOAD_CONST               0 (None)
              9 RETURN_VALUE        

Примечание 2 в первой строке; это номер строки в исходном источнике, который содержит код Python, который использовался для этих инструкций. Объекты Python кода co_lnotab и co_firstlineno атрибуты, которые позволяют сопоставлять байт-коды с номерами строк в исходном источнике. dis делает это для вас при отображении разборки.