Содержание страницы
32.12. dis – Дизассемблер байт-кода Python¶dis – Disassembler for Python bytecode
Исходный код: Lib/dis.py
Модуль dis поддерживает анализ байт-кода CPython путём
eго дизассемблирования. Байт-код CPython, который этот модуль принимает на вход,
определён в файле Include/opcode.h и используется компилятором и
интерпретатором.
Особенность реализации CPython: Байт-код – деталь реализации интерпретатора CPython! Не гарантируется, что байт-код не будет добавлен, удалён или изменён в разных версиях Python. Не следует рассчитывать, что этот модуль будет работать в других виртуальных машинах Python или в других выпусках Python.
Пример: Дана функция myfunc():
def myfunc(alist):
return len(alist)
следующая команда позволяет получить дизассемблированный код myfunc():
>>> dis.dis(myfunc)
2 0 LOAD_GLOBAL 0 (len)
3 LOAD_FAST 0 (alist)
6 CALL_FUNCTION 1
9 RETURN_VALUE
(«2» – это номер строки).
Модуль dis определяет следующие функции и константы:
-
dis.dis([bytesource])¶ Дизассемблирует объект bytesource. bytesource может обозначать модуль, класс, метод, функцию или объект кода. Для модуля дизассемблируются все функции. Для класса – все методы. Для отдельной последовательности кода выводится одна строка на каждую инструкцию байткода. Если объект не указан, дизассемблируется последний traceback.
-
dis.distb([tb])¶ Дизассемблирует функцию на вершине стека traceback, используя последний traceback, если ни один не был передан. Инструкция, вызвавшая исключение, отмечается.
-
dis.disassemble(code[, lasti])¶ Дизассемблирует объект кода, указывая последнюю инструкцию, если был указан lasti. Вывод разделён на следующие столбцы:
номер строки для первой инструкции каждой строки
текущая инструкция, помечена как
-->,инструкция с меткой, помечена
>>,адрес инструкции,
название кода операции,
параметры операции и
интерпретация параметров в скобках.
Интерпретация параметров распознаёт имена локальных и глобальных переменных, константные значения, цели переходов и операторы сравнения.
-
dis.disco(code[, lasti])¶ Синоним для
disassemble(). Его удобнее набирать, и он сохранён для совместимости с более ранними версиями Python.
-
dis.findlinestarts(code)¶ Эта функция-генератор использует атрибуты
co_firstlinenoиco_lnotabобъекта кода code для поиска смещений, соответствующих началам строк в исходном коде. Они возвращаются в виде пар(offset, lineno).
-
dis.findlabels(code)¶ Определяет все смещения в объекте кода code, которые являются целями перехода, и\nвозвращает список этих смещений.
-
dis.opname¶ Последовательность имён операций, индексируемая с помощью байткода.
-
dis.opmap¶ Словарь, сопоставляющий имена операций с байткодами.
-
dis.cmp_op¶ Последовательность всех имён операций сравнения.
-
dis.hasconst¶ Последовательность байткодов, обращающихся к константе.
-
dis.hasfree¶ Последовательность байткодов, обращающихся к свободной переменной.
-
dis.hasname¶ Последовательность байткодов, обращающихся к атрибуту по имени.
-
dis.hasjrel¶ Последовательность байткодов, имеющих относительную цель перехода.
-
dis.hasjabs¶ Последовательность байткодов, имеющих абсолютную цель перехода.
-
dis.haslocal¶ Последовательность байткодов, обращающихся к локальной переменной.
-
dis.hascompare¶ Последовательность байткодов логических операций.
32.12.1. Инструкции байт-кода Python¶Python Bytecode Instructions
В настоящее время компилятор Python генерирует следующие инструкции байткода.
-
STOP_CODE()¶ Указывает компилятору на конец кода, не используется интерпретатором.
-
NOP()¶ Код, который ничего не делает. Используется в качестве заполнителя оптимизатором байт-кода.
-
POP_TOP()¶ Удаляет элемент с вершины стека (TOS).
-
ROT_TWO()¶ Меняет местами два верхних элемента стека.
-
ROT_THREE()¶ Поднимает второй и третий элементы стека на одну позицию вверх, перемещает верхний вниз на третью позицию.
-
ROT_FOUR()¶ Поднимает второй, третий и четвёртый элементы стека на одну позицию вверх, перемещает верхний элемент вниз на четвёртую позицию.
-
DUP_TOP()¶ Дублирует ссылку на вершине стека.
Унарные операции берут верхушку стека, применяют операцию и помещают результат обратно в стек.
-
UNARY_POSITIVE()¶ Реализует
TOS = +TOS.
-
UNARY_NEGATIVE()¶ Реализует
TOS = -TOS.
-
UNARY_NOT()¶ Реализует
TOS = not TOS.
-
UNARY_CONVERT()¶ Реализует
TOS = `TOS`.
-
UNARY_INVERT()¶ Реализует
TOS = ~TOS.
-
GET_ITER()¶ Реализует
TOS = iter(TOS).
Бинарные операции удаляют из стека элемент с вершины (TOS) и второй сверху элемент стека (TOS1). Они выполняют операцию и помещают результат обратно в стек.
-
BINARY_POWER()¶ Реализует
TOS = TOS1 ** TOS.
-
BINARY_MULTIPLY()¶ Реализует
TOS = TOS1 * TOS.
-
BINARY_DIVIDE()¶ Реализует
TOS = TOS1 / TOS, когдаfrom __future__ import divisionне действует.
-
BINARY_FLOOR_DIVIDE()¶ Реализует
TOS = TOS1 // TOS.
-
BINARY_TRUE_DIVIDE()¶ Реализует
TOS = TOS1 / TOS, когдаfrom __future__ import divisionдействует.
-
BINARY_MODULO()¶ Реализует
TOS = TOS1 % TOS.
-
BINARY_ADD()¶ Реализует
TOS = TOS1 + TOS.
-
BINARY_SUBTRACT()¶ Реализует
TOS = TOS1 - TOS.
-
BINARY_SUBSCR()¶ Реализует
TOS = TOS1[TOS].
-
BINARY_LSHIFT()¶ Реализует
TOS = TOS1 << TOS.
-
BINARY_RSHIFT()¶ Реализует
TOS = TOS1 >> TOS.
-
BINARY_AND()¶ Реализует
TOS = TOS1 & TOS.
-
BINARY_XOR()¶ Реализует
TOS = TOS1 ^ TOS.
-
BINARY_OR()¶ Реализует
TOS = TOS1 | TOS.
Операции на месте аналогичны бинарным: они также удаляют TOS и TOS1 и помещают результат обратно в стек, но операция выполняется на месте, если TOS1 это поддерживает, и результирующий TOS может (но не обязан) быть исходным TOS1.
-
INPLACE_POWER()¶ Реализует операцию на месте
TOS = TOS1 ** TOS.
-
INPLACE_MULTIPLY()¶ Реализует операцию на месте
TOS = TOS1 * TOS.
-
INPLACE_DIVIDE()¶ Реализует
TOS = TOS1 / TOSна месте, когдаfrom __future__ import divisionне действует.
-
INPLACE_FLOOR_DIVIDE()¶ Реализует операцию на месте
TOS = TOS1 // TOS.
-
INPLACE_TRUE_DIVIDE()¶ Реализует
TOS = TOS1 / TOSна месте, когдаfrom __future__ import divisionдействует.
-
INPLACE_MODULO()¶ Реализует операцию на месте
TOS = TOS1 % TOS.
-
INPLACE_ADD()¶ Реализует операцию на месте
TOS = TOS1 + TOS.
-
INPLACE_SUBTRACT()¶ Реализует операцию на месте
TOS = TOS1 - TOS.
-
INPLACE_LSHIFT()¶ Реализует операцию на месте
TOS = TOS1 << TOS.
-
INPLACE_RSHIFT()¶ Реализует операцию на месте
TOS = TOS1 >> TOS.
-
INPLACE_AND()¶ Реализует операцию на месте
TOS = TOS1 & TOS.
-
INPLACE_XOR()¶ Реализует операцию на месте
TOS = TOS1 ^ TOS.
-
INPLACE_OR()¶ Реализует операцию на месте
TOS = TOS1 | TOS.
Опкоды среза принимают до трёх параметров.
-
SLICE+0()¶ Реализует
TOS = TOS[:].
-
SLICE+1()¶ Реализует
TOS = TOS1[TOS:].
-
SLICE+2()¶ Реализует
TOS = TOS1[:TOS].
-
SLICE+3()¶ Реализует
TOS = TOS2[TOS1:TOS].
Присваивание среза требует ещё один дополнительный параметр. Как и любая инструкция, они ничего не помещают в стек.
-
STORE_SLICE+0()¶ Реализует
TOS[:] = TOS1.
-
STORE_SLICE+1()¶ Реализует
TOS1[TOS:] = TOS2.
-
STORE_SLICE+2()¶ Реализует
TOS1[:TOS] = TOS2.
-
STORE_SLICE+3()¶ Реализует
TOS2[TOS1:TOS] = TOS3.
-
DELETE_SLICE+0()¶ Реализует
del TOS[:].
-
DELETE_SLICE+1()¶ Реализует
del TOS1[TOS:].
-
DELETE_SLICE+2()¶ Реализует
del TOS1[:TOS].
-
DELETE_SLICE+3()¶ Реализует
del TOS2[TOS1:TOS].
-
STORE_SUBSCR()¶ Реализует
TOS1[TOS] = TOS2.
-
DELETE_SUBSCR()¶ Реализует
del TOS1[TOS].
Разные опкоды.
-
PRINT_EXPR()¶ Реализует выражение-инструкцию для интерактивного режима. TOS удаляется из стека и выводится на печать. В неинтерактивном режиме выражение-инструкция завершается с помощью
POP_TOP.
-
PRINT_ITEM()¶ Выводит TOS в файлоподобный объект, связанный с
sys.stdout. Есть одна такая инструкция для каждого элемента в оператореprint.
-
PRINT_ITEM_TO()¶ Как
PRINT_ITEM, но выводит элемент, второй от TOS, в файлоподобный объект на TOS. Это используется расширенным оператором print.
-
PRINT_NEWLINE()¶ Выводит новую строку на
sys.stdout. Это генерируется как последняя операция оператораprint, если только оператор не заканчивается запятой.
-
PRINT_NEWLINE_TO()¶ Как
PRINT_NEWLINE, но выводит новую строку в файлоподобный объект на TOS. Это используется расширенным оператором print.
-
CONTINUE_LOOP(target)¶ Продолжает цикл при выполнении оператора
continue. target – это адрес, на который нужно перейти (должен быть инструкцияFOR_ITER).
-
LIST_APPEND(i)¶ Вызывает
list.append(TOS[-i], TOS). Используется для реализации списковых включений. Хотя добавленное значение извлекается из стека, объект списка остаётся в стеке, чтобы быть доступным для последующих итераций цикла.
-
LOAD_LOCALS()¶ Помещает ссылку на локальные переменные текущей области видимости в стек. Это используется в коде для определения класса: после вычисления тела класса локальные переменные передаются определению класса.
-
RETURN_VALUE()¶ Возвращает TOS вызывающей стороне функции.
-
IMPORT_STAR()¶ Загружает все имена, не начинающиеся с
'_', из модуля TOS в локальное пространство имён. Модуль удаляется после загрузки всех имён. Этот опкод реализуетfrom module import *.
-
EXEC_STMT()¶ Реализует
exec TOS2,TOS1,TOS. Компилятор заполняет отсутствующие необязательные параметры значениемNone.
-
POP_BLOCK()¶ Удаляет один блок из стека блоков. В каждом фрейме есть стек блоков, представляющий вложенные циклы, операторы try и т.п.
-
END_FINALLY()¶ Завершает предложение
finally. Интерпретатор запоминает, нужно ли повторно возбуждать исключение или функция возвращает значение, и продолжает со следующим внешним блоком.
-
BUILD_CLASS()¶ Создаёт новый объект класса. TOS – словарь методов, TOS1 – кортеж имён базовых классов, а TOS2 – имя класса.
-
SETUP_WITH(delta)¶ Эта инструкция выполняет несколько операций перед началом блока with. Во-первых, она загружает
__exit__()из менеджера контекста и помещает его в стек для последующего использованияWITH_CLEANUP. Затем вызывается__enter__(), и в стек помещается блок finally, указывающий на delta. Наконец, результат вызова метода enter помещается в стек. Следующая инструкция либо игнорирует его (POP_TOP), либо сохраняет в переменную(ые) (STORE_FAST,STORE_NAMEилиUNPACK_SEQUENCE).
-
WITH_CLEANUP()¶ Очищает стек при выходе из блока оператора
with. На вершине стека находятся 1–3 значения, указывающие, как/почему был выполнен блок finally:TOP =
None(TOP, SECOND) = (
WHY_{RETURN,CONTINUE}), retvalTOP =
WHY_*; retval под ним отсутствует(TOP, SECOND, THIRD) = exc_info()
Под ними находится EXIT, привязанный метод
__exit__()менеджера контекста.В последнем случае вызывается
EXIT(TOP, SECOND, THIRD), иначеEXIT(None, None, None).ВЫХОД удаляется из стека, оставляя значения над ним в том же порядке. Кроме того, если стек представляет исключение, и вызов функции возвращает «истинное» значение, эта информация «стирается», чтобы предотвратить повторное возбуждение исключения через
END_FINALLY. (Но нелокальные переходы всё же следует возобновлять.)
Все следующие опкоды требуют аргументов. Аргумент занимает два байта, причём старший байт идёт последним.
-
STORE_NAME(namei)¶ Реализует
name = TOS. namei – это индекс name в атрибутеco_namesобъекта кода. Компилятор пытается использоватьSTORE_FASTилиSTORE_GLOBAL, если возможно.
-
DELETE_NAME(namei)¶ Реализует
del name, где namei – это индекс в атрибутco_namesобъекта кода.
-
UNPACK_SEQUENCE(count)¶ Распаковывает TOS в count отдельных значений, которые помещаются в стек справа налево.
-
DUP_TOPX(count)¶ Дублирует count элементов, сохраняя их порядок. Из-за ограничений реализации count должен быть от 1 до 5 включительно.
-
STORE_ATTR(namei)¶ Реализует
TOS.name = TOS1, где namei – это индекс имени вco_names.
-
DELETE_ATTR(namei)¶ Реализует
del TOS.name, используя namei как индекс вco_names.
-
STORE_GLOBAL(namei)¶ Работает как
STORE_NAME, но сохраняет имя как глобальное.
-
DELETE_GLOBAL(namei)¶ Работает как
DELETE_NAME, но удаляет глобальное имя.
-
LOAD_CONST(consti)¶ Помещает
co_consts[consti]в стек.
-
LOAD_NAME(namei)¶ Помещает значение, связанное с
co_names[namei], в стек.
-
BUILD_TUPLE(count)¶ Создаёт кортеж, потребляя count элементов из стека, и помещает полученный кортеж в стек.
-
BUILD_LIST(count)¶ Работает как
BUILD_TUPLE, но создаёт список.
-
BUILD_SET(count)¶ Работает как
BUILD_TUPLE, но создаёт множество.Новое в версии 2.7.
-
BUILD_MAP(count)¶ Помещает новый объект словаря в стек. Словарь предварительно настраивается на хранение count записей.
-
LOAD_ATTR(namei)¶ Заменяет TOS на
getattr(TOS, co_names[namei]).
-
COMPARE_OP(opname)¶ Выполняет логическую операцию. Имя операции можно найти в
cmp_op[opname].
-
IMPORT_NAME(namei)¶ Импортирует модуль
co_names[namei]. TOS и TOS1 извлекаются и предоставляют аргументы fromlist и level для__import__(). Объект модуля помещается в стек. Текущее пространство имён не затрагивается: для корректного оператора import последующая инструкцияSTORE_FASTизменяет пространство имён.
-
IMPORT_FROM(namei)¶ Загружает атрибут
co_names[namei]из модуля, находящегося в TOS. Полученный объект помещается в стек для последующего сохранения инструкциейSTORE_FAST.
-
JUMP_FORWARD(delta)¶ Увеличивает счётчик байт-кода на delta.
-
POP_JUMP_IF_TRUE(target)¶ Если TOS истинно, устанавливает счётчик байткода в target. TOS извлекается из стека.
-
POP_JUMP_IF_FALSE(target)¶ Если TOS ложно, устанавливает счётчик байткода в target. TOS извлекается из стека.
-
JUMP_IF_TRUE_OR_POP(target)¶ Если TOS истинно, устанавливает счётчик байткода в target и оставляет TOS на стеке. В противном случае (TOS ложно) TOS извлекается.
-
JUMP_IF_FALSE_OR_POP(target)¶ Если TOS ложно, устанавливает счётчик байткода в target и оставляет TOS на стеке. В противном случае (TOS истинно) TOS извлекается.
-
JUMP_ABSOLUTE(target)¶ Устанавливает счётчик байткода в target.
-
FOR_ITER(delta)¶ TOS– это итератор. Вызвать его методnext(). Если он возвращает новое значение, поместить его в стек (оставив итератор под ним). Если итератор сообщает, что он исчерпан,TOSизвлекается, и счётчик байткода увеличивается на delta.
-
LOAD_GLOBAL(namei)¶ Загружает глобальную переменную
co_names[namei]в стек.
-
SETUP_LOOP(delta)¶ Помещает блок для цикла в стек блоков. Блок начинается с текущей инструкции и имеет размер delta байт.
-
SETUP_EXCEPT(delta)¶ Помещает блок try из конструкции try-except в стек блоков. delta указывает на первый блок except.
-
SETUP_FINALLY(delta)¶ Pushes a try block from a try-except clause onto the block stack. delta points to the finally block.
-
STORE_MAP()¶ Сохраняет пару ключ-значение в словаре. Извлекает ключ и значение, оставляя словарь в стеке.
-
LOAD_FAST(var_num)¶ Помещает ссылку на локальную переменную
co_varnames[var_num]в стек.
-
STORE_FAST(var_num)¶ Сохраняет TOS в локальную переменную
co_varnames[var_num].
-
DELETE_FAST(var_num)¶ Удаляет локальную переменную
co_varnames[var_num].
-
LOAD_CLOSURE(i)¶ Помещает ссылку на ячейку, содержащуюся в слоте i хранилища ячеек и свободных переменных. Имя переменной –
co_cellvars[i], если i меньше длины co_cellvars. В противном случае –co_freevars[i - len(co_cellvars)].
-
LOAD_DEREF(i)¶ Загружает ячейку, содержащуюся в слоте i хранилища ячеек и свободных переменных. Помещает ссылку на объект, который содержит ячейка, в стек.
-
STORE_DEREF(i)¶ Сохраняет TOS в ячейку, содержащуюся в слоте i хранилища ячеек и свободных переменных.
-
SET_LINENO(lineno)¶ Этот опкод устарел.
-
RAISE_VARARGS(argc)¶ Вызывает исключение. argc указывает количество аргументов инструкции raise, от 0 до 3. Обработчик находит traceback как TOS2, параметр как TOS1, а исключение как TOS.
-
CALL_FUNCTION(argc)¶ Вызывает вызываемый объект. Младший байт argc указывает количество позиционных аргументов, старший байт – количество именованных аргументов. Стек содержит именованные аргументы сверху (если есть), затем позиционные аргументы под ними (если есть), затем вызываемый объект под ними. Каждый именованный аргумент представлен двумя значениями в стеке: имя аргумента и его значение, при этом значение аргумента находится выше имени в стеке. Позиционные аргументы помещаются в стек в порядке передачи вызываемому объекту, причём самый правый позиционный аргумент – сверху.
CALL_FUNCTIONизвлекает все аргументы и вызываемый объект из стека, вызывает вызываемый объект с этими аргументами и помещает возвращаемое значение, возвращённое вызываемым объектом.
-
MAKE_FUNCTION(argc)¶ Помещает новый объект функции в стек. TOS – это код, связанный с функцией. Функция определяется как имеющая argc параметров по умолчанию, которые находятся ниже TOS.
-
MAKE_CLOSURE(argc)¶ Создаёт новый объект функции, устанавливает его слот func_closure и помещает его в стек. TOS – это код, связанный с функцией, TOS1 – кортеж, содержащий ячейки для свободных переменных замыкания. Функция также имеет argc параметров по умолчанию, которые находятся ниже ячеек.
-
BUILD_SLICE(argc)¶ Помещает объект среза в стек. argc должен быть 2 или 3. Если равно 2, помещается
slice(TOS1, TOS); если 3, помещаетсяslice(TOS2, TOS1, TOS). Подробнее см. встроенную функциюslice().
-
EXTENDED_ARG(ext)¶ Добавляет префикс к любой опкоду, чей аргумент слишком велик, чтобы поместиться в стандартные два байта. ext содержит два дополнительных байта, которые вместе с аргументом последующего опкода образуют четырёхбайтовый аргумент, причём ext является двумя старшими байтами.
-
CALL_FUNCTION_VAR(argc)¶ Вызывает вызываемый объект, аналогично
CALL_FUNCTION. argc представляет количество ключевых и позиционных аргументов, так же какCALL_FUNCTION. Вершина стека содержит итерируемый объект с дополнительными позиционными аргументами. Под ним находятся ключевые аргументы (если есть), позиционные аргументы (если есть) и вызываемый объект, так же какCALL_FUNCTION. Перед вызовом вызываемого объекта итерируемый объект «распаковывается», и его содержимое добавляется к переданным позиционным аргументам. Итерируемый объект игнорируется при вычислении значенияargc.
-
CALL_FUNCTION_KW(argc)¶ Вызывает вызываемый объект, аналогично
CALL_FUNCTION. argc представляет количество ключевых и позиционных аргументов, так же какCALL_FUNCTION. Вершина стека содержит отображение (mapping) с дополнительными ключевыми аргументами. Под ним находятся ключевые аргументы (если есть), позиционные аргументы (если есть) и вызываемый объект, так же какCALL_FUNCTION. Перед вызовом вызываемого объекта отображение на вершине стека «распаковывается», и его содержимое добавляется к переданным ключевым аргументам. Отображение на вершине стека игнорируется при вычислении значенияargc.
-
CALL_FUNCTION_VAR_KW(argc)¶ Вызывает вызываемый объект, аналогично
CALL_FUNCTION_VARиCALL_FUNCTION_KW. argc представляет количество ключевых и позиционных аргументов, так же какCALL_FUNCTION. Вершина стека содержит отображение, как вCALL_FUNCTION_KW. Под ним находится итерируемый объект, как вCALL_FUNCTION_VAR. Под ними находятся ключевые аргументы (если есть), позиционные аргументы (если есть) и вызываемый объект, так же какCALL_FUNCTION. Перед вызовом вызываемого объекта отображение и итерируемый объект «распаковываются», и их содержимое передаётся как ключевые и позиционные аргументы соответственно, так же как вCALL_FUNCTION_VARиCALL_FUNCTION_KW. Отображение и итерируемый объект игнорируются при вычислении значенияargc.
-
HAVE_ARGUMENT()¶ Это не совсем опкод. Он определяет разделительную линию между опкодами, которые не принимают аргументы
< HAVE_ARGUMENT, и теми, которые принимают>= HAVE_ARGUMENT.