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

    A detailed image of a reticulated python showcasing its patterned scales and intricate skin texture.
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    symtable en Python: analiza scopes

    Aprende symtable en Python para analizar scopes, locals, globals, parámetros, imports, nonlocals, closures y namespaces del compilador.

    Ler mais

    Tempo de leitura: 9 minutos
    27/08/2026
    Gold Bitcoin coins displayed on a sparkling gold texture, representing digital currency and finance.
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    tokenize en Python: lee tokens del código

    Aprende tokenize en Python para leer tokens, comentarios, encoding, indentación y posiciones, además de transformar y reconstruir código con seguridad.

    Ler mais

    Tempo de leitura: 6 minutos
    27/08/2026
    Side view of contemplating female assistant in casual style standing near shelves and choosing file with documents
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    zipapp en Python: crea archivos .pyz

    Aprende zipapp en Python para crear archivos .pyz, definir entry points, incluir dependencias puras, usar recursos y distribuir CLIs seguras.

    Ler mais

    Tempo de leitura: 6 minutos
    27/08/2026
    High-angle view of woman coding on a laptop, with a Python book nearby. Ideal for programming and tech content.
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    sysconfig en Python: rutas y build

    Aprende sysconfig en Python para descubrir rutas, schemes, headers, flags de build, ABI, extensiones nativas y entornos virtuales.

    Ler mais

    Tempo de leitura: 6 minutos
    27/08/2026
    Código binario verde sobre el teclado de un portátil, representando datos internos de Python.
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    marshal en Python: formato interno

    Aprende marshal en Python para objetos internos y bytecode, con versiones, allow_code, caches descartables, límites y riesgos de entrada no

    Ler mais

    Tempo de leitura: 6 minutos
    27/08/2026
    Vibrant assortment of pickled vegetables in jars with red fabric covers, displayed on shelves.
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    copyreg en Python: personaliza pickle

    Aprende copyreg en Python para personalizar pickle, registrar reducers, versionar estado, evitar conflictos globales y serializar con seguridad.

    Ler mais

    Tempo de leitura: 6 minutos
    27/08/2026