opcode en Python: explora el bytecode

Publicado el: 15/08/2026
Tempo de leitura: 5 minutos
Monitor con código binario que representa instrucciones opcode del bytecode de Python

opcode en Python abarca los códigos numéricos, nombres legibles y clasificaciones de las instrucciones de bytecode de CPython. En la documentación actual, las colecciones públicas aparecen junto a dis: dis desmonta el código compilado y las tablas de opcode describen las operaciones.

El tema es útil para analizadores, depuradores, investigación del intérprete y experimentos educativos. El bytecode es un detalle de implementación. Las instrucciones cambian entre versiones, no son portables a otras máquinas virtuales y no deben convertirse en contrato permanente de una aplicación.

Opcodes y bytecode

Cuando CPython compila una función, produce un objeto de código con instrucciones. Cada una posee código numérico, nombre y, con frecuencia, argumento.

import dis

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

for instruccion in dis.get_instructions(sumar):
    print(
        instruccion.opcode,
        instruccion.opname,
        instruccion.arg,
        instruccion.argrepr,
    )

Prefiere dis.get_instructions() frente a interpretar co_code manualmente. La API considera argumentos extendidos, posiciones, caches y cambios de versión.

Colecciones públicas

Las colecciones documentadas incluyen opname, opmap, hasarg, hasconst, hasfree, hasname, haslocal y hasjump, expuestas por dis.

import dis

print(dis.opmap['LOAD_CONST'])
print(dis.opname[dis.opmap['RETURN_VALUE']])
print(dis.hasconst[:5])

El módulo interno opcode participa en la implementación, pero las bibliotecas deberían usar interfaces documentadas de dis.

Mapea nombre a número

dis.opmap transforma nombres de operaciones en enteros.

codigo = dis.opmap.get('LOAD_FAST')
if codigo is None:
    raise RuntimeError('Opcode no disponible')
print(codigo)

Usa get() si soportas varias versiones. Las operaciones pueden añadirse, renombrarse, fusionarse o eliminarse. Python 3.14 incluye instrucciones nuevas para referencias prestadas, templates, monitorización y constantes comunes.

Mapea número a nombre

dis.opname se indexa con el opcode numérico.

for numero, nombre in enumerate(dis.opname):
    if not nombre.startswith('<'):
        print(numero, nombre)

Las entradas reservadas pueden tener nombres de marcador. No todos los valores representan instrucciones reales del bytecode final.

Detecta operaciones con argumento

dis.hasarg enumera operaciones que utilizan argumento. Es preferible al límite histórico HAVE_ARGUMENT.

for instruccion in dis.get_instructions(sumar):
    if instruccion.opcode in dis.hasarg:
        print(instruccion.opname, instruccion.arg)

El significado depende de la operación: índice de constante, nombre, variable local, celda de closure, flags o delta de salto.

Constantes, nombres, locales y closures

Las colecciones especializadas clasifican argumentos:

  • hasconst accede a co_consts.
  • hasname usa nombres de co_names.
  • haslocal usa variables locales.
  • hasfree trabaja con celdas y closures.
def clasificar(instruccion):
    op = instruccion.opcode
    if op in dis.hasconst:
        return 'constante'
    if op in dis.hasname:
        return 'nombre'
    if op in dis.haslocal:
        return 'local'
    if op in dis.hasfree:
        return 'closure'
    return 'otro'

Para la clasificación de ámbitos antes del bytecode, consulta symtable en Python.

Saltos y flujo de control

dis.hasjump agrupa operaciones con objetivo de salto. CPython moderno usa saltos relativos y su representación ha cambiado.

for instruccion in dis.get_instructions(funcion):
    if instruccion.opcode in dis.hasjump:
        print(instruccion.opname, instruccion.jump_target)

Usa Instruction.jump_target en lugar de calcular destinos con bytes. Caches, labels lógicos y saltos hacia atrás vuelven frágil la aritmética manual.

Calcula el efecto de pila

dis.stack_effect() informa cómo cambia la pila de evaluación.

for instruccion in dis.get_instructions(sumar):
    efecto = dis.stack_effect(
        instruccion.opcode,
        instruccion.arg,
    )
    print(instruccion.opname, efecto)

Para operaciones condicionales, pasa jump=True o jump=False. El valor predeterminado devuelve el efecto máximo.

Instrucciones especializadas

Desde Python 3.11, el intérprete adapta y especializa bytecode durante la ejecución. Instruction expone baseopcode y baseopname para identificar la operación general.

for instruccion in dis.get_instructions(
    funcion,
    adaptive=True,
):
    print(instruccion.opname, instruccion.baseopname)

Las herramientas que buscan nombres especializados exactos pueden fallar cuando la función se calienta. Agrupar por baseopname suele ser mejor.

Caches inline

Algunas operaciones reservan entradas de cache. Instruction.cache_info entrega información estructurada.

for instruccion in dis.get_instructions(funcion):
    if instruccion.cache_info:
        print(instruccion.opname, instruccion.cache_info)

No interpretes bytes de cache como instrucciones normales; sus datos pueden parecer opcodes arbitrarios.

Pseudoinstrucciones

El compilador utiliza operaciones que se sustituyen o eliminan antes del bytecode final. Las colecciones modernas también pueden incluir instrucciones instrumentadas.

Para código ejecutable, itera un objeto real con get_instructions() y no presupongas que cada entrada global puede aparecer en runtime.

Operaciones de comparación

dis.cmp_op contiene nombres de comparaciones asociadas a COMPARE_OP. El argumento bruto puede incluir flags, por lo que conviene usar argrepr.

codigo = compile('a <= b', '<expr>', 'eval')
for instruccion in dis.get_instructions(codigo):
    if instruccion.opname == 'COMPARE_OP':
        print(instruccion.argrepr)

Cuenta tipos de instrucciones

from collections import Counter
import dis


def contar(objeto):
    return Counter(
        instruccion.baseopname
        for instruccion in dis.get_instructions(objeto)
    )

print(contar(sumar))

El reporte es útil para aprendizaje y comparación estructural, pero la cantidad de instrucciones no estima bien el rendimiento. El costo depende de objetos, llamadas, caches y memoria.

Analiza fuente sin ejecutarla

Una string puede compilarse y desmontarse sin ejecutar el objeto.

codigo = compile(
    'resultado = funcion(valor)',
    '<analisis>',
    'exec',
)
for instruccion in dis.get_instructions(codigo):
    print(instruccion.opname)

Compilar entradas enormes todavía consume recursos. Aplica límites a fuente externa.

No construyas blacklists de opcode

Bloquear IMPORT_NAME, LOAD_ATTR o CALL no crea una sandbox. Los objetos permitidos pueden ofrecer rutas indirectas a capacidades peligrosas y los cambios del compilador rompen la lista.

Ejecuta código no confiable en otro proceso o contenedor con permisos, CPU, memoria, red, sistema de archivos y tiempo limitados.

Relación con dis

La guía de dis en Python explica desmontaje completo, objetos Bytecode, posiciones, caches y tracebacks. Opcode es la capa más específica de tablas y categorías.

No confundas opcodes de pickle

La guía de pickletools en Python también trabaja con opcodes, pero pertenecen a la máquina virtual de pickle, no al bytecode de CPython.

Compatibilidad

No persistas números como protocolo duradero. Guarda la versión exacta y la implementación junto a cada reporte y regenera el análisis cuando cambia el entorno.

Una herramienta multiplataforma debe comprobar platform.python_implementation() y rechazar máquinas virtuales no soportadas.

Pruebas

Prueba funciones, closures, clases, comprehensions, generadores, coroutines, pattern matching, excepciones y ámbitos de anotación. Ejecuta la suite en cada versión soportada.

Incluye bytecode frío y adaptativo, caches, saltos y posiciones. Evita snapshots textuales rígidos; verifica propiedades semánticas.

Buenas prácticas

  • Usa APIs documentadas de dis.
  • Prefiere objetos Instruction.
  • Agrupa especializaciones con baseopname.
  • Considera caches y pseudoinstrucciones.
  • Registra versión e implementación.
  • No uses blacklists como sandbox.
  • No presupongas estabilidad numérica.
  • Prueba cada versión objetivo.

Conclusión

opcode en Python es la capa de metadatos de las instrucciones de CPython. Mediante las colecciones documentadas en dis, una herramienta puede mapear nombres, números, argumentos, saltos, constantes, closures y efectos de pila.

Úsalo para análisis y aprendizaje, no como contrato portable. Consulta la documentación oficial de colecciones de opcode y el código fuente oficial de opcode en CPython.

Compartilhe:

Facebook
WhatsApp
Twitter
LinkedIn

Contenido del artículo

    Artículos relacionados

    Desarrollador investigando consumo de memoria con tracemalloc en Python
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    tracemalloc en Python: detecta fugas

    Usa tracemalloc en Python para comparar snapshots, localizar crecimiento de memoria e investigar fugas en aplicaciones.

    Ler mais

    Tempo de leitura: 6 minutos
    15/08/2026
    Código con anotaciones de tipos que representa introspección con annotationlib en Python
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    annotationlib en Python: lee anotaciones

    Aprende annotationlib en Python 3.14 para recuperar anotaciones como valores, ForwardRef o strings y controlar riesgos de ejecución.

    Ler mais

    Tempo de leitura: 5 minutos
    14/08/2026
    Archivadores organizados que representan módulos importados directamente desde archivos ZIP con zipimport en Python
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    zipimport en Python: importa desde ZIP

    Aprende zipimport en Python para cargar módulos y paquetes desde archivos ZIP, usar importadores y proteger sistemas de plugins.

    Ler mais

    Tempo de leitura: 5 minutos
    14/08/2026
    Diagrama de directorios que representa rutas site-packages y configuración del módulo site en Python
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    site en Python: entiende las rutas

    Aprende el módulo site en Python para entender site-packages, user site, archivos .pth, sitecustomize, usercustomize y opciones de inicio.

    Ler mais

    Tempo de leitura: 7 minutos
    14/08/2026
    Icono de instalador que representa el bootstrap offline de pip con ensurepip en Python
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    ensurepip en Python: restaura pip

    Aprende ensurepip en Python para instalar o restaurar pip sin internet, elegir entorno, scripts, upgrade y evitar conflictos con el

    Ler mais

    Tempo de leitura: 6 minutos
    14/08/2026
    Paquete de software que representa metadatos consultados con importlib.metadata en Python
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    importlib.metadata en Python: paquetes

    Aprende importlib.metadata en Python para consultar versiones, dependencias, archivos, metadatos y entry points de paquetes instalados.

    Ler mais

    Tempo de leitura: 6 minutos
    14/08/2026