¿Cómo leer el bytecode python?
python-2.7 (1)
Los números antes de los bytecodes se compensan con los bytecodes binarios originales:
>>> func.__code__.co_code
''d/x01/x00}/x00/x00d/x00/x00S''
Algunos códigos de byte vienen con información adicional (argumentos) que influyen en cómo funciona cada bytecode, el desplazamiento le indica en qué posición se encontró el bytecode en la posición de bytestream.
El bytecode LOAD_CONST
(ASCII d
, hex 64) está seguido de dos bytes adicionales que codifican una referencia a una constante asociada con el bytecode, por ejemplo. Como resultado, el STORE_FAST
operación STORE_FAST
(ASCII }
, hex 7D) se encuentra en el índice 3.
La documentación del módulo dis
enumera lo que significa cada instrucción. Para LOAD_CONST
, dice:
Empuja
co_consts[consti]
en la pila.
que hace referencia a la estructura de co_consts
que siempre está presente con un objeto de código; el compilador construye que:
>>> func.__code__.co_consts
(None, 1)
El código de operación carga el índice 1 de esa estructura (los 01 00 bytes en el bytecode codifican un 1), y dis
ha buscado eso para usted; es el valor 1
.
La siguiente instrucción, STORE_FAST
se describe como:
Almacena TOS en los
co_varnames[var_num]
localesco_varnames[var_num]
.
Aquí TOS se refiere a Top Of Stack; tenga en cuenta que LOAD_CONST
acaba de LOAD_CONST
algo en la pila, el valor 1
. co_varnames
es otra estructura; hace referencia a nombres de variables locales, el código de referencia hace referencia al índice 0:
>>> func.__code__.co_varnames
(''x'',)
También buscó eso, y el nombre que usaste en tu código es x
. Por lo tanto, este opcode almacenó 1
en x
.
Otro LOAD_CONST
carga None
en la pila desde el índice 0, seguido de RETURN_VALUE
:
Vuelve con TOS a la persona que llama a la función.
por lo que esta instrucción toma la parte superior de la pila (con la constante None
) y regresa de este bloque de código. None
es el valor de retorno predeterminado para las funciones sin una declaración de return
explícita.
Omitió algo de la salida del dis
, los números de línea:
>>> dis.dis(func)
2 0 LOAD_CONST 1 (1)
3 STORE_FAST 0 (x)
6 LOAD_CONST 0 (None)
9 RETURN_VALUE
Note el 2
en la primera línea; ese es el número de línea en la fuente original que contiene el código de Python que se utilizó para estas instrucciones. Los objetos de código Python tienen co_lnotab
y co_firstlineno
que le permiten asignar co_lnotab
co_firstlineno
a números de línea en la fuente original. dis
hace esto por usted cuando se muestra un desmontaje.
Estoy teniendo muchas dificultades para entender el código de bytes de Python y su módulo dis
.
import dis
def func():
x = 1
dis.dis(func)
El código anterior cuando se escribe en el intérprete produce el siguiente resultado:
0 LOAD_CONST 1(1)
3 STORE_FAST 0(x)
6 LOAD_CONST 0(NONE)
9 RETURN_VALUE
P.ej:
¿Cuál es el significado de LOAD_CONST
, STORE_FAST
y los números como 0
, 3
, 6
y 9
?
Un recurso específico, donde puedo encontrar esta información sería muy apreciado.