A code object’s co_code is a string of two-byte instructions. CPython runs
them on a stack, keeping a separate block stack for loops and try statements
in 3.8 and 3.9.
Encoding
Every instruction is two bytes: the opcode, then an 8-bit argument. An opcode below
90 (HAVE_ARGUMENT) ignores its argument, and the byte is normally 0.
EXTENDED_ARG. An argument that does not fit in eight
bits has one or more EXTENDED_ARG instructions before it. Each holds
eight more bits, high bits first, so an argument of 0x0102 is
90 01 and then the instruction with argument 02. Three of
them give a 32-bit argument.
Jumps. A jump’s argument is a count of bytes, always even. A
relative jump (JUMP_FORWARD, FOR_ITER, the
SETUP_* instructions, CALL_FINALLY) counts from the
instruction after it. An absolute jump (JUMP_ABSOLUTE,
POP_JUMP_IF_*, JUMP_IF_*_OR_POP,
JUMP_IF_NOT_EXC_MATCH) is an offset from the start of
co_code.
In the table, TOS is the top of the stack and TOS1 the value below it; “–” means the instruction is not in that release. Numbers 82, 162 and 163 mean different things in 3.8 and 3.9, so the release decides the name.
Opcodes
| Name | 3.8 | 3.9 | Meaning |
|---|---|---|---|
POP_TOP | 1 | 1 | Removes TOS |
ROT_TWO | 2 | 2 | Swaps the top two values |
ROT_THREE | 3 | 3 | Moves the second and third values up; TOS goes to third place |
DUP_TOP | 4 | 4 | Pushes a copy of TOS |
DUP_TOP_TWO | 5 | 5 | Pushes copies of the top two values, in the same order |
ROT_FOUR | 6 | 6 | Moves the second, third and fourth values up; TOS goes to fourth place |
NOP | 9 | 9 | Does nothing |
UNARY_POSITIVE | 10 | 10 | TOS = +TOS |
UNARY_NEGATIVE | 11 | 11 | TOS = -TOS |
UNARY_NOT | 12 | 12 | TOS = not TOS |
UNARY_INVERT | 15 | 15 | TOS = ~TOS |
BINARY_MATRIX_MULTIPLY | 16 | 16 | Pops two values, pushes TOS1 @ TOS |
INPLACE_MATRIX_MULTIPLY | 17 | 17 | Pops two values, pushes TOS1 @ TOS done in place |
BINARY_POWER | 19 | 19 | Pops two values, pushes TOS1 ** TOS |
BINARY_MULTIPLY | 20 | 20 | Pops two values, pushes TOS1 * TOS |
BINARY_MODULO | 22 | 22 | Pops two values, pushes TOS1 % TOS |
BINARY_ADD | 23 | 23 | Pops two values, pushes TOS1 + TOS |
BINARY_SUBTRACT | 24 | 24 | Pops two values, pushes TOS1 - TOS |
BINARY_SUBSCR | 25 | 25 | Pops two values, pushes TOS1[TOS] |
BINARY_FLOOR_DIVIDE | 26 | 26 | Pops two values, pushes TOS1 // TOS |
BINARY_TRUE_DIVIDE | 27 | 27 | Pops two values, pushes TOS1 / TOS |
INPLACE_FLOOR_DIVIDE | 28 | 28 | Pops two values, pushes TOS1 // TOS done in place |
INPLACE_TRUE_DIVIDE | 29 | 29 | Pops two values, pushes TOS1 / TOS done in place |
RERAISE | – | 48 | Re-raises the exception on top of the stack |
WITH_EXCEPT_START | – | 49 | Calls the function seven places down with the top three values: __exit__(*exc_info()) |
GET_AITER | 50 | 50 | TOS = TOS.__aiter__() |
GET_ANEXT | 51 | 51 | Pushes get_awaitable(TOS.__anext__()) |
BEFORE_ASYNC_WITH | 52 | 52 | Takes __aenter__ and __aexit__ from TOS; pushes __aexit__ and the result of __aenter__() |
BEGIN_FINALLY | 53 | – | Pushes NULL and starts a finally block |
END_ASYNC_FOR | 54 | 54 | Ends an async for loop, handling the exception from awaiting the next item |
INPLACE_ADD | 55 | 55 | Pops two values, pushes TOS1 + TOS done in place |
INPLACE_SUBTRACT | 56 | 56 | Pops two values, pushes TOS1 - TOS done in place |
INPLACE_MULTIPLY | 57 | 57 | Pops two values, pushes TOS1 * TOS done in place |
INPLACE_MODULO | 59 | 59 | Pops two values, pushes TOS1 % TOS done in place |
STORE_SUBSCR | 60 | 60 | TOS1[TOS] = TOS2 |
DELETE_SUBSCR | 61 | 61 | del TOS1[TOS] |
BINARY_LSHIFT | 62 | 62 | Pops two values, pushes TOS1 << TOS |
BINARY_RSHIFT | 63 | 63 | Pops two values, pushes TOS1 >> TOS |
BINARY_AND | 64 | 64 | Pops two values, pushes TOS1 & TOS |
BINARY_XOR | 65 | 65 | Pops two values, pushes TOS1 ^ TOS |
BINARY_OR | 66 | 66 | Pops two values, pushes TOS1 | TOS |
INPLACE_POWER | 67 | 67 | Pops two values, pushes TOS1 ** TOS done in place |
GET_ITER | 68 | 68 | TOS = iter(TOS) |
GET_YIELD_FROM_ITER | 69 | 69 | Leaves TOS if it is a generator or coroutine; otherwise TOS = iter(TOS) |
PRINT_EXPR | 70 | 70 | Pops TOS and prints it, as the interactive prompt does |
LOAD_BUILD_CLASS | 71 | 71 | Pushes builtins.__build_class__ |
YIELD_FROM | 72 | 72 | Pops TOS and delegates to it as a sub-iterator from a generator |
GET_AWAITABLE | 73 | 73 | TOS = get_awaitable(TOS) |
LOAD_ASSERTION_ERROR | – | 74 | Pushes AssertionError |
INPLACE_LSHIFT | 75 | 75 | Pops two values, pushes TOS1 << TOS done in place |
INPLACE_RSHIFT | 76 | 76 | Pops two values, pushes TOS1 >> TOS done in place |
INPLACE_AND | 77 | 77 | Pops two values, pushes TOS1 & TOS done in place |
INPLACE_XOR | 78 | 78 | Pops two values, pushes TOS1 ^ TOS done in place |
INPLACE_OR | 79 | 79 | Pops two values, pushes TOS1 | TOS done in place |
WITH_CLEANUP_START | 81 | – | Starts cleaning up when a with block exits, calling __exit__() and pushing its result |
WITH_CLEANUP_FINISH | 82 | – | Finishes cleaning up after WITH_CLEANUP_START; a true result from __exit__() silences the exception |
LIST_TO_TUPLE | – | 82 | Pops a list, pushes a tuple of the same values |
RETURN_VALUE | 83 | 83 | Returns TOS to the caller |
IMPORT_STAR | 84 | 84 | Pops a module and copies its public names into the namespace: from module import * |
SETUP_ANNOTATIONS | 85 | 85 | Makes an empty __annotations__ dictionary in the namespace if it has none |
YIELD_VALUE | 86 | 86 | Pops TOS and yields it from a generator |
POP_BLOCK | 87 | 87 | Removes one block from the block stack |
END_FINALLY | 88 | – | Ends a finally clause: continues, jumps to a saved address or re-raises, according to TOS |
POP_EXCEPT | 89 | 89 | Removes an exception handler block; restores the exception state from the last three values popped |
STORE_NAME | 90 | 90 | Stores TOS under the name at argument index of co_names, in the namespace |
DELETE_NAME | 91 | 91 | Deletes that name from the namespace |
UNPACK_SEQUENCE | 92 | 92 | Pops a sequence and pushes its argument-many items, with the first on top |
FOR_ITER | 93 | 93 | TOS is an iterator. Pushes its next value, or pops it and jumps when it is finished (relative) |
UNPACK_EX | 94 | 94 | Unpacks with a star target: the low byte of the argument is the count before the star, the high byte the count after |
STORE_ATTR | 95 | 95 | TOS.name = TOS1; argument is an index in co_names |
DELETE_ATTR | 96 | 96 | del TOS.name; argument is an index in co_names |
STORE_GLOBAL | 97 | 97 | Pops TOS and stores it as a global; argument is an index in co_names |
DELETE_GLOBAL | 98 | 98 | Deletes a global; argument is an index in co_names |
LOAD_CONST | 100 | 100 | Pushes co_consts[argument] |
LOAD_NAME | 101 | 101 | Pushes the value of the name at index of co_names |
BUILD_TUPLE | 102 | 102 | Pops argument-many values, pushes a tuple of them |
BUILD_LIST | 103 | 103 | Pops argument-many values, pushes a list of them |
BUILD_SET | 104 | 104 | Pops argument-many values, pushes a set of them |
BUILD_MAP | 105 | 105 | Pops argument × 2 values, pushes a dictionary: {…, TOS3: TOS2, TOS1: TOS} |
LOAD_ATTR | 106 | 106 | TOS = TOS.name; argument is an index in co_names |
COMPARE_OP | 107 | 107 | Pops two values, pushes the result of the comparison named in the comparison table |
IMPORT_NAME | 108 | 108 | Imports the module named at index of co_names; TOS and TOS1 give fromlist and level; pushes the module |
IMPORT_FROM | 109 | 109 | Pushes the attribute named at index of co_names, taken from the module in TOS, which stays |
JUMP_FORWARD | 110 | 110 | Jumps forward by the argument (relative) |
JUMP_IF_FALSE_OR_POP | 111 | 111 | If TOS is false, jumps and keeps it; otherwise pops it (absolute) |
JUMP_IF_TRUE_OR_POP | 112 | 112 | If TOS is true, jumps and keeps it; otherwise pops it (absolute) |
JUMP_ABSOLUTE | 113 | 113 | Jumps to the byte offset given by the argument (absolute) |
POP_JUMP_IF_FALSE | 114 | 114 | Pops TOS and jumps if it is false (absolute) |
POP_JUMP_IF_TRUE | 115 | 115 | Pops TOS and jumps if it is true (absolute) |
LOAD_GLOBAL | 116 | 116 | Pushes the global named at index of co_names |
IS_OP | – | 117 | Pops two values, pushes TOS1 is TOS; is not when the argument is 1 |
CONTAINS_OP | – | 118 | Pops two values, pushes TOS1 in TOS; not in when the argument is 1 |
JUMP_IF_NOT_EXC_MATCH | – | 121 | Pops two values and jumps if TOS1 is not an exception matching TOS (absolute) |
SETUP_FINALLY | 122 | 122 | Pushes a try block; the argument (relative) points to the finally or first except block |
LOAD_FAST | 124 | 124 | Pushes local variable co_varnames[argument] |
STORE_FAST | 125 | 125 | Pops TOS into local variable co_varnames[argument] |
DELETE_FAST | 126 | 126 | Deletes local variable co_varnames[argument] |
RAISE_VARARGS | 130 | 130 | Raises an exception: argument 0 re-raises, 1 raises TOS, 2 raises TOS1 with __cause__ TOS |
CALL_FUNCTION | 131 | 131 | Calls with argument-many positional arguments on the stack, the callable below them, and pushes the result |
MAKE_FUNCTION | 132 | 132 | Pops a qualified name, a code object and the values in the flags table, and pushes a new function |
BUILD_SLICE | 133 | 133 | Pushes a slice made from 2 or 3 values, according to the argument |
LOAD_CLOSURE | 135 | 135 | Pushes the cell at this index: cells first, then free variables |
LOAD_DEREF | 136 | 136 | Pushes the value of the cell at this index |
STORE_DEREF | 137 | 137 | Pops TOS into the cell at this index |
DELETE_DEREF | 138 | 138 | Empties the cell at this index |
CALL_FUNCTION_KW | 141 | 141 | Calls with keyword arguments: TOS is a tuple of their names, the argument is the total number of arguments |
CALL_FUNCTION_EX | 142 | 142 | Calls with an iterable of positional arguments and, if bit 0 of the argument is set, a mapping of keyword arguments above it |
SETUP_WITH | 143 | 143 | Calls __enter__(), saves __exit__, pushes a finally block at the argument (relative) and the result of entering |
EXTENDED_ARG | 144 | 144 | Gives the next instruction’s argument eight more high bits |
LIST_APPEND | 145 | 145 | list.append(TOS1[-i], TOS), for list comprehensions; the list stays |
SET_ADD | 146 | 146 | set.add(TOS1[-i], TOS), for set comprehensions; the set stays |
MAP_ADD | 147 | 147 | Adds TOS1 as key and TOS as value to the dictionary i places down, for dictionary comprehensions |
LOAD_CLASSDEREF | 148 | 148 | Like LOAD_DEREF, but looks in the locals first; used in class bodies |
BUILD_LIST_UNPACK | 149 | – | Pops argument-many iterables, pushes one list: [*x, *y] |
BUILD_MAP_UNPACK | 150 | – | Pops argument-many mappings, pushes one dictionary: {**x, **y} |
BUILD_MAP_UNPACK_WITH_CALL | 151 | – | The same for f(**x, **y); the callable is at position argument + 2 |
BUILD_TUPLE_UNPACK | 152 | – | Pops argument-many iterables, pushes one tuple: (*x, *y) |
BUILD_SET_UNPACK | 153 | – | Pops argument-many iterables, pushes one set: {*x, *y} |
SETUP_ASYNC_WITH | 154 | 154 | Sets up a finally block for async with; the argument is relative |
FORMAT_VALUE | 155 | 155 | Formats a value for an f-string: see the flags table |
BUILD_CONST_KEY_MAP | 156 | 156 | Pops a tuple of keys from TOS and argument-many values, pushes a dictionary |
BUILD_STRING | 157 | 157 | Joins argument-many strings from the stack, pushes the result |
BUILD_TUPLE_UNPACK_WITH_CALL | 158 | – | The same as BUILD_TUPLE_UNPACK, for f(*x, *y); the callable is at position argument + 1 |
LOAD_METHOD | 160 | 160 | Loads a method named at index of co_names from TOS, pushing the method and self, or NULL and the attribute |
CALL_METHOD | 161 | 161 | Calls what LOAD_METHOD left, with argument-many positional arguments; pushes the result |
CALL_FINALLY | 162 | – | Pushes the next instruction’s address and jumps, to call a finally block as a subroutine (relative) |
LIST_EXTEND | – | 162 | list.extend(TOS1[-i], TOS), to build lists |
POP_FINALLY | 163 | – | Cleans up the value stack and block stack for break, continue and return in a finally block; a non-zero argument keeps TOS |
SET_UPDATE | – | 163 | set.update(TOS1[-i], TOS), to build sets |
DICT_MERGE | – | 164 | Like DICT_UPDATE, but raises an exception on a duplicate key |
DICT_UPDATE | – | 165 | dict.update(TOS1[-i], TOS), to build dictionaries |
COMPARE_OP arguments
In 3.8 the argument picks one of twelve entries. In 3.9 only the first six exist:
is, in and the exception test have their own
instructions.
| Argument | Operator | Present in |
|---|---|---|
| 0 | < | 3.8, 3.9 |
| 1 | <= | 3.8, 3.9 |
| 2 | == | 3.8, 3.9 |
| 3 | != | 3.8, 3.9 |
| 4 | > | 3.8, 3.9 |
| 5 | >= | 3.8, 3.9 |
| 6 | in | 3.8 |
| 7 | not in | 3.8 |
| 8 | is | 3.8 |
| 9 | is not | 3.8 |
| 10 | exception match | 3.8 |
| 11 | BAD | 3.8 |
MAKE_FUNCTION flags
The argument is a set of bits. Each bit means one more value lies on the stack, below the code object and the qualified name. The lowest bit’s value is deepest.
| Bit | Value on the stack |
|---|---|
| 0x01 | A tuple of default values for positional parameters |
| 0x02 | A dictionary of default values for keyword-only parameters |
| 0x04 | A dictionary of annotations |
| 0x08 | A tuple of cells for free variables, making a closure |
FORMAT_VALUE flags
Pops a value, formats it with PyObject_Format, and pushes the string.
| Bits | Meaning |
|---|---|
flags & 3 = 0 | Format the value as it is |
flags & 3 = 1 | Call str() first |
flags & 3 = 2 | Call repr() first |
flags & 3 = 3 | Call ascii() first |
flags & 4 | A format specification is popped from the stack before the value |