> **Источник:** https://python-all.ru/3.0/library/dis.html
>
> «Документация Python на русском» – неофициальный перевод официальной документации Python: версии от 2.6 до 3.16, полнотекстовый поиск, английский оригинал рядом с переводом. Эта Markdown-версия страницы предназначена для работы с LLM: вставьте её в ChatGPT, Claude или Cursor.

---

# `dis` – Дисассемблер байт-кода Python

Модуль `dis` поддерживает анализ Python [*байт-кода*](https://python-all.ru/3.0/glossary.html#term-bytecode) путём его дизассемблирования. Поскольку ассемблера для Python не существует, этот модуль определяет язык ассемблера Python. Байт-код Python, который подаётся на вход этому модулю, определён в файле `Include/opcode.h` и используется компилятором и интерпретатором.

Пример: дана функция `myfunc()`:

```python
def myfunc(alist):
    return len(alist)
```

Для получения дизассемблированного кода `myfunc()` можно использовать следующую команду:

```python
>>> 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]dis.dis([bytesource])`

Дизассемблирует объект

*bytesource*

.

*bytesource*

может обозначать модуль, класс, метод, функцию или объект кода. Для модуля дизассемблируются все функции. Для класса – все методы. Для одной последовательности кода выводится одна строка на каждую инструкцию байт-кода. Если объект не указан, дизассемблируется последняя трассировка.

#### `[dis.distb]dis.distb([tb])`

Дизассемблирует функцию на вершине стека трассировки, используя последнюю трассировку, если ни одна не была передана. Указывается инструкция, вызвавшая исключение.

#### `[dis.disassemble]dis.disassemble(code[, lasti])`

Дизассемблирует объект кода, указывая последнюю инструкцию, если был указан *lasti*. Вывод разделён на следующие столбцы:

1. номер строки для первой инструкции каждой строки
2. текущая инструкция, помечена как `-->`,
3. инструкция с меткой, помечена `>>`,
4. адрес инструкции,
5. название кода операции,
6. параметры операции и
7. интерпретация параметров в скобках.

Интерпретация параметров распознаёт имена локальных и глобальных переменных, константные значения, цели переходов и операторы сравнения.

#### `[dis.disco]dis.disco(code[, lasti])`

Синоним для

[`disassemble()`](https://python-all.ru/3.0/library/dis.html#dis.disassemble)

. Его проще набирать, и он сохранён для совместимости с более ранними версиями Python.

#### `[dis.findlinestarts]dis.findlinestarts(code)`

Эта функция-генератор использует атрибуты

`co_firstlineno`

и

`co_lnotab`

объекта кода

*code*

для поиска смещений, соответствующих началам строк в исходном коде. Они генерируются в виде пар

`(offset, lineno)`

.

#### `[dis.findlabels]dis.findlabels(code)`

Определяет все смещения в объекте кода

*code*

, которые являются целями перехода, и\\nвозвращает список этих смещений.

#### `[dis.opname]dis.opname`

Последовательность имён операций, индексируемая с помощью байткода.

#### `[dis.opmap]dis.opmap`

Словарь, отображающий байт-коды в имена операций.

#### `[dis.cmp_op]dis.cmp_op`

Последовательность всех имён операций сравнения.

#### `[dis.hasconst]dis.hasconst`

Последовательность байткодов, имеющих постоянный параметр.

#### `[dis.hasfree]dis.hasfree`

Последовательность байткодов, обращающихся к свободной переменной.

#### `[dis.hasname]dis.hasname`

Последовательность байткодов, обращающихся к атрибуту по имени.

#### `[dis.hasjrel]dis.hasjrel`

Последовательность байткодов, имеющих относительную цель перехода.

#### `[dis.hasjabs]dis.hasjabs`

Последовательность байткодов, имеющих абсолютную цель перехода.

#### `[dis.haslocal]dis.haslocal`

Последовательность байткодов, обращающихся к локальной переменной.

#### `[dis.hascompare]dis.hascompare`

Последовательность байткодов логических операций.

## Инструкции байткода Python

В настоящее время компилятор 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 = не TOS`

.

**`UNARY_INVERT`()**

Реализует

`TOS = ~TOS`

.

**`GET_ITER`()**

Реализует

`TOS = iter(TOS)`

.

Бинарные операции удаляют из стека элемент с вершины (TOS) и второй сверху элемент стека (TOS1). Они выполняют операцию и помещают результат обратно в стек.

**`BINARY_POWER`()**

Реализует

`TOS = TOS1 ** TOS`

.

**`BINARY_MULTIPLY`()**

Реализует

`TOS = TOS1 * TOS`

.

**`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`()**

Реализует in-place:

`TOS = TOS1 ** TOS`

.

**`INPLACE_MULTIPLY`()**

Реализует in-place:

`TOS = TOS1 * TOS`

.

**`INPLACE_FLOOR_DIVIDE`()**

Реализует in-place:

`TOS = TOS1 // TOS`

.

**`INPLACE_TRUE_DIVIDE`()**

Реализует на месте

`TOS = TOS1 / TOS`

, когда

`from __future__ import division`

действует.

**`INPLACE_MODULO`()**

Реализует in-place:

`TOS = TOS1 % TOS`

.

**`INPLACE_ADD`()**

Реализует in-place:

`TOS = TOS1 + TOS`

.

**`INPLACE_SUBTRACT`()**

Реализует in-place:

`TOS = TOS1 - TOS`

.

**`INPLACE_LSHIFT`()**

Реализует in-place:

`TOS = TOS1 << TOS`

.

**`INPLACE_RSHIFT`()**

Реализует in-place:

`TOS = TOS1 >> TOS`

.

**`INPLACE_AND`()**

Реализует in-place:

`TOS = TOS1 & TOS`

.

**`INPLACE_XOR`()**

Реализует in-place:

`TOS = TOS1 ^ TOS`

.

**`INPLACE_OR`()**

Реализует in-place:

`TOS = TOS1 | TOS`

.

**`STORE_SUBSCR`()**

Реализует

`TOS1[TOS] = TOS2`

.

**`DELETE_SUBSCR`()**

Реализует

`del TOS1[TOS]`

.

Разные опкоды.

**`PRINT_EXPR`()**

Реализует оператор выражения для интерактивного режима. TOS удаляется из стека и выводится на печать. В неинтерактивном режиме оператор выражения завершается

`POP_STACK`

.

**`BREAK_LOOP`()**

Завершает цикл при выполнении оператора

[`break`](https://python-all.ru/3.0/reference/simple_stmts.html#break)

.

**`CONTINUE_LOOP`(*target*)**

Продолжает цикл при выполнении оператора

[`continue`](https://python-all.ru/3.0/reference/simple_stmts.html#continue)

.

*target*

– это адрес перехода (должен быть инструкцией

`FOR_ITER`

).

**`SET_ADD`()**

Calls

`set.add(TOS1, TOS)`

. Used to implement set comprehensions.

**`LIST_APPEND`()**

Calls

`list.append(TOS1, TOS)`

. Used to implement list comprehensions.

**`LOAD_LOCALS`()**

Pushes a reference to the locals of the current scope on the stack. This is used in the code for a class definition: After the class body is evaluated, the locals are passed to the class definition.

**`RETURN_VALUE`()**

Возвращает TOS вызывающей стороне функции.

**`YIELD_VALUE`()**

Извлекает

`TOS`

и возвращает его из

[*генератора*](https://python-all.ru/3.0/glossary.html#term-generator)

.

**`IMPORT_STAR`()**

Загружает все символы, не начинающиеся с

`'_'`

, непосредственно из модуля TOS в локальное пространство имён. Модуль извлекается после загрузки всех имён. Этот опкод реализует

`from module import *`

.

**`POP_BLOCK`()**

Удаляет один блок из стека блоков. Для каждого фрейма существует стек блоков, обозначающий вложенные циклы, операторы try и тому подобное.

**`POP_EXCEPT`()**

Удаляет один блок из стека блоков. Извлечённый блок должен быть блоком обработчика исключений, который неявно создаётся при входе в обработчик except. Помимо извлечения лишних значений из стека фрейма, последние три извлечённых значения используются для восстановления состояния исключения.

**`END_FINALLY`()**

Завершает блок

[`finally`](https://python-all.ru/3.0/reference/compound_stmts.html#finally)

. Интерпретатор запоминает, нужно ли повторно возбуждать исключение или функция возвращается, и продолжает со следующим внешним блоком.

**`LOAD_BUILD_CLASS`()**

Помещает

`builtins.__build_class__()`

в стек. Позже она вызывается инструкцией

`CALL_FUNCTION`

для создания класса.

**`WITH_CLEANUP`()**

Очищает стек при выходе из блока оператора [`with`](https://python-all.ru/3.0/reference/compound_stmts.html#with). TOS – это привязанный метод [`__exit__()`](https://python-all.ru/3.0/reference/datamodel.html#object.__exit__) менеджера контекста. Ниже TOS находятся 1–3 значения, указывающие, каким образом/почему был выполнен блок finally:

- SECOND = `None`
- (SECOND, THIRD) = (`WHY_{RETURN,CONTINUE}`), retval
- SECOND = `WHY_*`; под ним нет retval
- (SECOND, THIRD, FOURTH) = exc\_info()

В последнем случае вызывается `TOS(SECOND, THIRD, FOURTH)`, иначе `TOS(None, None, None)`. Кроме того, TOS удаляется из стека.

Если стек представляет исключение, *и* вызов функции возвращает истинное значение, эта информация «зануляется» и заменяется одним значением `WHY_SILENCED`, чтобы предотвратить повторное возбуждение исключения инструкцией `END_FINALLY`. (Но нелокальные переходы все равно будут возобновлены.)

**`STORE_LOCALS`**

Извлекает TOS из стека и сохраняет его как

`f_locals`

текущего фрейма. Используется при построении класса.

Все следующие опкоды требуют аргументов. Аргумент занимает два байта, причём старший байт идёт последним.

**`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*

отдельных значений, которые помещаются в стек справа налево.

**`UNPACK_EX`(*counts*)**

Реализует присваивание с целевой переменной со звёздочкой: распаковывает итерируемый объект в TOS в отдельные значения, где общее количество значений может быть меньше количества элементов в итерируемом объекте: одно из новых значений будет списком всех оставшихся элементов.

Младший байт *counts* – это количество значений до спискового значения, а старший байт *counts* – количество значений после него. Результирующие значения помещаются в стек справа налево.

**`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`

, но создает множество.

**`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__()`](https://python-all.ru/3.0/library/functions.html#__import__)

. Объект модуля помещается в стек. Текущее пространство имен не затрагивается: для правильного оператора import последующая инструкция

`STORE_FAST`

изменяет пространство имен.

**`IMPORT_FROM`(*namei*)**

Загружает атрибут

`co_names[namei]`

из модуля, находящегося в TOS. Полученный объект помещается в стек, чтобы затем быть сохраненным инструкцией

`STORE_FAST`

.

**`JUMP_FORWARD`(*delta*)**

Увеличивает счётчик байт-кода на

*delta*

.

**`JUMP_IF_TRUE`(*delta*)**

Если TOS истинно, увеличить счётчик байткода на

*delta*

. TOS остаётся на стеке.

**`JUMP_IF_FALSE`(*delta*)**

Если TOS ложно, увеличить счётчик байткода на

*delta*

. TOS не изменяется.

**`JUMP_ABSOLUTE`(*target*)**

Устанавливает счётчик байткода в

*target*

.

**`FOR_ITER`(*delta*)**

`TOS`

– это

[*итератор*](https://python-all.ru/3.0/glossary.html#term-iterator)

. Вызовите его метод

`__next__()`

. Если это возвращает новое значение, поместите его в стек (оставив итератор под ним). Если итератор сигнализирует, что он исчерпан,

`TOS`

извлекается, а счетчик байт-кода увеличивается на

*delta*

.

**`LOAD_GLOBAL`(*namei*)**

Загружает глобальную переменную с именем

`co_names[namei]`

в стек.

**`SETUP_LOOP`(*delta*)**

Помещает блок для цикла в стек блоков. Блок начинается с текущей инструкции и имеет размер

*delta*

байт.

**`SETUP_EXCEPT`(*delta*)**

Помещает блок try из конструкции try-except в стек блоков.

*delta*

указывает на первый блок except.

**`SETUP_FINALLY`(*delta*)**

Помещает блок try из конструкции try-except в стек блоков.

*delta*

указывает на блок finally.

**`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*

указывает количество позиционных параметров, старший байт – количество именованных параметров. В стеке опкод сначала находит именованные параметры. Для каждого именованного аргумента значение находится поверх ключа. Под именованными параметрами в стеке располагаются позиционные параметры, причем самый правый параметр – наверху. Под параметрами находится вызываемый объект функции. Снимает со стека все аргументы функции и саму функцию, затем помещает в стек возвращаемое значение.

**`MAKE_FUNCTION`(*argc*)**

Помещает новый объект функции в стек. TOS – это код, связанный с функцией. Объект функции определяется как имеющий

*argc*

параметров по умолчанию, которые находятся под TOS.

**`MAKE_CLOSURE`(*argc*)**

Создаёт новый объект функции, устанавливает его слот

*\_\_closure\_\_*

и помещает его в стек. TOS – это код, связанный с функцией, TOS1 – кортеж содержащий ячейки для свободных переменных замыкания. Функция также имеет

*argc*

параметров по умолчанию, которые находятся под ячейками.

**`BUILD_SLICE`(*argc*)**

Помещает объект среза в стек. *argc* должен быть равен 2 или 3. Если он равен 2, помещается `slice(TOS1, TOS)`; если 3 – `slice(TOS2, TOS1, TOS)`. Подробнее см. встроенную функцию [`slice()`](https://python-all.ru/3.0/library/functions.html#slice).

**`EXTENDED_ARG`(*ext*)**

Является префиксом для любого опкода, аргумент которого слишком велик, чтобы поместиться в стандартные два байта.

*ext*

содержит два дополнительных байта, которые вместе с аргументом последующего опкода образуют четырехбайтовый аргумент, причем

*ext*

является двумя старшими байтами.

**`CALL_FUNCTION_VAR`(*argc*)**

Вызывает функцию.

*argc*

интерпретируется так же, как в

`CALL_FUNCTION`

. Верхний элемент стека содержит список аргументов переменной длины, за которым следуют именованные и позиционные аргументы.

**`CALL_FUNCTION_KW`(*argc*)**

Вызывает функцию.

*argc*

интерпретируется так же, как в

`CALL_FUNCTION`

. Верхний элемент в стеке содержит словарь именованных аргументов, за которым следуют явные именованные и позиционные аргументы.

**`CALL_FUNCTION_VAR_KW`(*argc*)**

Вызывает функцию.

*argc*

интерпретируется так же, как в

`CALL_FUNCTION`

. Верхний элемент в стеке содержит словарь именованных аргументов, за которым следуют кортеж переменных аргументов, а затем явные именованные и позиционные аргументы.

**`HAVE_ARGUMENT`()**

Это не совсем опкод. Он обозначает разделительную линию между опкодами, не принимающими аргументы

`< HAVE_ARGUMENT`

, и теми, которые принимают

`>= HAVE_ARGUMENT`

.
