Skip to content

Python dis Module: Detailed Overview and Examples

The dis module in Python is a built-in library for disassembling Python bytecode into a human-readable format. It allows developers to analyze and understand the low-level operations that Python performs for a given piece of code. This is particularly useful for optimization, debugging, and understanding the internals of Python.

Importing the dis Module

To use the functions and methods from the dis module, you need to import it:

import dis

Key Functions and Methods

1. Disassembling Functions

dis.dis(object)

Disassembles the bytecode of the given object (function, method, or code object).

Example
import dis

def example_function(x):
    return x + 1

dis.dis(example_function)

Output:

  2           0 LOAD_FAST                0 (x)
              2 LOAD_CONST               1 (1)
              4 BINARY_ADD
              6 RETURN_VALUE

2. Disassembling Strings

dis.disassemble(code, lasti=-1, *, file=None)

Disassembles the bytecode of a code object. This is a lower-level interface that is typically used internally by dis.dis.

Example
import dis

code = compile('x + 1', '<string>', 'eval')
dis.disassemble(code)

Output:

  1           0 LOAD_NAME                0 (x)
              2 LOAD_CONST               0 (1)
              4 BINARY_ADD
              6 RETURN_VALUE

3. Disassembling Classes and Modules

dis.dis(obj=None, *, file=None, depth=None)

Disassembles classes and modules. The depth parameter specifies how deep to disassemble (default is unlimited).

Example
import dis

class ExampleClass:
    def method(self, x):
        return x * 2

dis.dis(ExampleClass)

Output:

Disassembly of method:
  2           0 LOAD_FAST                1 (x)
              2 LOAD_CONST               1 (2)
              4 BINARY_MULTIPLY
              6 RETURN_VALUE

4. Getting Bytecode Instructions

dis.get_instructions(x, *, first_line=None, current_offset=None)

Returns an iterator over dis.Instruction instances for the given function, method, source code string, or code object.

Example
import dis

def example_function(x):
    return x - 1

instructions = dis.get_instructions(example_function)
for instr in instructions:
    print(instr)

Output:

Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='x', argrepr='x', offset=0, starts_line=2, is_jump_target=False)
Instruction(opname='LOAD_CONST', opcode=100, arg=1, argval=1, argrepr='1', offset=2, starts_line=2, is_jump_target=False)
Instruction(opname='BINARY_SUBTRACT', opcode=24, arg=None, argval=None, argrepr='', offset=4, starts_line=2, is_jump_target=False)
Instruction(opname='RETURN_VALUE', opcode=83, arg=None, argval=None, argrepr='', offset=6, starts_line=2, is_jump_target=False)

5. Showing Bytecode

dis.show_code(co, *, file=None)

Displays details of a code object, including the argument count, number of locals, stack size, and flags.

Example
import dis

def example_function(x):
    return x / 2

dis.show_code(example_function.__code__)

Output:

Name:              example_function
Filename:          <ipython-input-2-49b1e5eab4df>
Argument count:    1
Positional-only arguments: 0
Kw-only arguments: 0
Number of locals:  2
Stack size:        2
Flags:             OPTIMIZED, NEWLOCALS, NOFREE
Constants:
  0: None
  1: 2
Names:
  0: x
Variable names:
  0: x

Practical Examples

Example 1: Analyzing a Function

import dis

def add(a, b):
    return a + b

dis.dis(add)

Output:

  2           0 LOAD_FAST                0 (a)
              2 LOAD_FAST                1 (b)
              4 BINARY_ADD
              6 RETURN_VALUE

Example 2: Analyzing a Class Method

import dis

class Calculator:
    def multiply(self, a, b):
        return a * b

dis.dis(Calculator.multiply)

Output:

  2           0 LOAD_FAST                1 (a)
              2 LOAD_FAST                2 (b)
              4 BINARY_MULTIPLY
              6 RETURN_VALUE

Example 3: Using get_instructions

import dis

def subtract(a, b):
    return a - b

instructions = dis.get_instructions(subtract)
for instr in instructions:
    print(instr)

Output:

Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='a', argrepr='a', offset=0, starts_line=2, is_jump_target=False)
Instruction(opname='LOAD_FAST', opcode=124, arg=1, argval='b', argrepr='b', offset=2, starts_line=2, is_jump_target=False)
Instruction(opname='BINARY_SUBTRACT', opcode=24, arg=None, argval=None, argrepr='', offset=4, starts_line=2, is_jump_target=False)
Instruction(opname='RETURN_VALUE', opcode=83, arg=None, argval=None, argrepr='', offset=6, starts_line=2, is_jump_target=False)

Example 4: Showing Code Object Details

import dis

def divide(a, b):
    return a / b

dis.show_code(divide.__code__)

Output:

Name:              divide
Filename:          <ipython-input-4-0d7b92749d8e>
Argument count:    2
Positional-only arguments: 0
Kw-only arguments: 0
Number of locals:  2
Stack size:        2
Flags:             OPTIMIZED, NEWLOCALS, NOFREE
Constants:
  0: None
Names:
  0: a
  1: b
Variable names:
  0: a
  1: b

Conclusion

The dis module in Python is a powerful tool for disassembling and analyzing Python bytecode. It provides detailed insights into the low-level operations performed by Python, which can be useful for optimization, debugging, and understanding the internals of Python code. By leveraging the functions and methods provided by the dis module, developers can gain a deeper understanding of how Python executes their code and make informed decisions to improve performance and correctness.