dis en Python: entiende el bytecode

Publicado el: 27/08/2026
Tempo de leitura: 5 minutos
Detailed shot of a Jungle Carpet Python (Morelia spilota cheynei) in its natural habitat.

El módulo dis desensambla code objects de Python y muestra las instrucciones de bytecode ejecutadas por el intérprete. Ayuda a estudiar cómo se compilan expresiones, funciones, loops, comprehensions, excepciones y llamadas. También sirve para enseñanza, debugging de herramientas, análisis de rendimiento y comparación entre versiones.

El bytecode es un detalle de implementación. Instrucciones, argumentos, offsets, caches y optimizaciones pueden cambiar entre releases, incluso menores. No construyas lógica de negocio, formatos persistentes o fronteras de seguridad alrededor de una secuencia exacta sin limitar y probar la versión del runtime.

Desensambla una función

dis.dis() acepta funciones, métodos, clases, módulos, strings de fuente y code objects.

import dis


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


dis.dis(sumar)

La salida muestra offsets, nombres de instrucciones, argumentos y representaciones útiles.

Compila una expresión

También puedes inspeccionar código compilado dinámicamente.

codigo = compile("resultado = x * 2", "ejemplo.py", "exec")
dis.dis(codigo)

compile() no ejecuta el fuente, pero la entrada no confiable todavía requiere límites.

Code objects

Las funciones exponen __code__ con bytecode, constantes, nombres, variables y metadatos.

code = sumar.__code__
print(code.co_varnames)
print(code.co_consts)
print(code.co_names)

Estos campos son para introspección y pueden evolucionar.

Instrucciones programáticas

dis.get_instructions() devuelve objetos Instruction y es más fiable que parsear texto.

for instruccion in dis.get_instructions(sumar):
    print(
        instruccion.offset,
        instruccion.opname,
        instruccion.arg,
        instruccion.argval,
    )

Usa campos nombrados.

Objeto Instruction

Puede contener nombre del opcode, argumento numérico, valor resuelto, representación, offset, posiciones y marca de jump target.

No todos los campos aplican a todos los opcodes.

Clase Bytecode

dis.Bytecode ofrece una interfaz iterable y helpers de formato.

bytecode = dis.Bytecode(sumar)
for instruccion in bytecode:
    print(instruccion.opname)

print(bytecode.dis())

Es útil para herramientas que guardan código y opciones de análisis.

Líneas y posiciones

Las instrucciones pueden asociarse a líneas e intervalos del fuente. Python moderno mantiene posiciones detalladas.

Acepta posiciones ausentes en código generado o transformado.

Offsets

Las opciones de desmontaje pueden mostrar offsets. Ayudan a interpretar jumps y exception tables.

No son IDs estables entre versiones o builds.

Instrucciones de carga

Constantes, nombres, globals, locals y atributos utilizan operaciones distintas.

x = 10

def usar_global():
    return x


def usar_local(x):
    return x

El bytecode muestra la diferencia, pero las reglas del lenguaje son la autoridad.

Operaciones binarias

Las expresiones cargan operandos y aplican operaciones.

def calcular(a, b):
    return (a + b) * 2

Python moderno puede usar una instrucción general con argumento para la operación concreta.

Constant folding

El compilador puede evaluar determinadas expresiones constantes.

def ejemplo():
    return 2 + 3

La salida puede contener solo la constante final. No todas las expresiones se doblan siempre.

Loops

Un for obtiene un iterator, solicita valores y usa jumps.

def totalizar(items):
    total = 0
    for item in items:
        total += item
    return total

El flujo ayuda a enseñar iteración, aunque los detalles cambian.

Condiciones y jumps

if, while, booleanos y short-circuit utilizan jumps.

is_jump_target identifica destinos.

for instruccion in dis.get_instructions(funcion):
    if instruccion.is_jump_target:
        print("destino", instruccion.offset)

Jumps relativos

La representación de jumps y unidades de offset ha cambiado. Usa argval y APIs actuales.

Declara versiones soportadas.

Llamadas

Las llamadas cargan callable y argumentos y usan instrucciones de preparación y ejecución.

La secuencia cambia con métodos, keywords y especialización adaptativa.

Comprehensions

List, set y dict comprehensions pueden producir code objects anidados.

def pares(valores):
    return [x * 2 for x in valores if x % 2 == 0]

dis.dis() puede mostrar esos objetos internos.

Generators

Funciones con yield usan instrucciones y flags para suspensión y reanudación.

No manipules su estado mediante internals.

async y await

Coroutines y async generators generan bytecode para espera, envío y reanudación.

La forma varía mucho entre versiones.

Excepciones

El manejo de excepciones ha cambiado significativamente en CPython.

No busques únicamente opcodes históricos para detectar bloques try.

Exception tables

Code objects modernos pueden almacenar tablas compactas fuera del flujo principal.

El formato interno no es contrato estable.

Intérprete adaptativo

CPython puede especializar instrucciones durante la ejecución según los tipos observados.

El desmontaje puede mostrar instrucciones originales o especializadas.

Opción adaptive

Las APIs actuales pueden enseñar instrucciones especializadas.

dis.dis(funcion, adaptive=True)

Ejecuta varias veces antes para observar warm-up, pero los resultados pueden variar.

show_caches

Los inline caches pueden mostrarse con show_caches=True.

dis.dis(funcion, show_caches=True)

Son internals de rendimiento. No los modifiques.

Cambios en runtime

La especialización puede cambiar la forma observada tras warm-up. Una herramienta de comparación debe controlar opciones.

Registra versión, opciones y cantidad de ejecuciones.

stack_effect

dis.stack_effect(opcode, oparg) calcula el efecto sobre la evaluation stack.

import dis
import opcode

efecto = dis.stack_effect(opcode.opmap["LOAD_CONST"], 0)
print(efecto)

Los jumps condicionales pueden requerir considerar el branch.

Análisis de stack

Sumar efectos linealmente no basta con jumps. Un análisis correcto propaga alturas por basic blocks.

Usa un verificador especializado.

Módulo opcode

opcode ofrece mapas y categorías.

import opcode

print(opcode.opmap.get("RETURN_VALUE"))

Los números cambian. Usa nombres de la versión actual.

Implementaciones diferentes

dis describe el bytecode soportado por su runtime, principalmente CPython.

No generalices detalles de CPython a garantías del lenguaje.

Análisis de rendimiento

El bytecode puede mostrar loads repetidos, llamadas en loops y alocaciones. Aun así, la inspección no es medición.

Usa timeit, cProfile y workloads reales.

Microbenchmarks

Compara con warm-up, repetición, aislamiento y control de ruido.

La especialización adaptativa exige medir el estado estable.

Límites de seguridad

La presencia de un opcode no prueba seguridad o peligro. Aliases, imports y comportamiento de objetos rompen allowlists simples.

No crees un sandbox validando bytecode y llamando exec().

Code objects no confiables

No cargues code objects de marshal o pickle no confiables en un proceso crítico solo para desmontarlos.

Aísla y limita recursos.

Diff de bytecode

Al comparar versiones, normaliza offsets, caches y campos inestables. Compara nombres y argumentos semánticos.

Separa cambios del lenguaje de diferencias de implementación.

Línea de comandos

El módulo puede desmontar un archivo.

python -m dis modulo.py

Es útil para aprendizaje e inspección rápida.

Combina con AST

AST muestra estructura de alto nivel y dis instrucciones después de compilar.

Consulta ast en Python.

Combina con tokenize

tokenize conserva comentarios y grafía que desaparecen en bytecode.

Consulta tokenize en Python.

Tests de herramientas

Ejecuta la suite en cada versión soportada. Incluye funciones simples, closures, generators, async, comprehensions, excepciones y pattern matching.

Usa fixtures específicas por versión.

Errores comunes

Los fallos frecuentes son asumir opcodes estables, parsear texto de dis, comparar offsets entre versiones, ignorar caches adaptativos, optimizar sin medir, tratar bytecode como sandbox, generalizar CPython y cargar code objects no confiables.

Conclusión

dis muestra cómo Python compila y ejecuta código al nivel de bytecode. Usa get_instructions() para análisis programático, controla caches y especialización y registra siempre la versión.

Trata el bytecode como detalle cambiante y perfila antes de optimizar. Consulta la documentación oficial de dis y la documentación de opcode.

Compartilhe:

Facebook
WhatsApp
Twitter
LinkedIn

Contenido del artículo

    Artículos relacionados

    Código en un monitor que representa acceso a memoria nativa con ctypes.memoryview_at en Python
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    ctypes.memoryview_at: memoria nativa sin copias

    Aprende ctypes.memoryview_at en Python para acceder a memoria nativa sin copias, validar punteros y reducir riesgos.

    Ler mais

    Tempo de leitura: 7 minutos
    12/10/2026
    Código Python en pantalla representando EnumDict y enumeraciones avanzadas
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    EnumDict: personaliza Enums con validación

    Aprende EnumDict en Python para personalizar EnumType, validar miembros y crear enumeraciones avanzadas con seguridad.

    Ler mais

    Tempo de leitura: 4 minutos
    11/10/2026
    Rack de servidores que representa el balanceo de conexiones con SO_REUSEPORT_LB en Python
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    SO_REUSEPORT_LB: reparte conexiones entre workers

    Aprende SO_REUSEPORT_LB en Python para distribuir conexiones entre workers con pruebas, portabilidad y cierre ordenado.

    Ler mais

    Tempo de leitura: 5 minutos
    11/10/2026
    Código Python asíncrono en un portátil para inspect.markcoroutinefunction
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    markcoroutinefunction: detecta wrappers async

    Aprende inspect.markcoroutinefunction en Python para identificar wrappers asíncronos, integrar frameworks y evitar detecciones incorrectas.

    Ler mais

    Tempo de leitura: 5 minutos
    10/10/2026
    Código Python para recorrer carpetas y archivos con Path.walk
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    Path.walk: recorre directorios con seguridad

    Aprende Path.walk en Python para recorrer directorios, filtrar archivos, tratar errores y controlar la travesía con seguridad.

    Ler mais

    Tempo de leitura: 5 minutos
    10/10/2026
    Depuración de un proceso Python en terminal con código
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    pdb -p: depura procesos Python en ejecución

    Aprende a conectar pdb a un proceso Python en ejecución, inspeccionar la pila y diagnosticar bloqueos de forma segura.

    Ler mais

    Tempo de leitura: 6 minutos
    09/10/2026