PVM学习日志

Code Object

# 每一个函数只会生成一个code object
import dis

def func(a, b):
    return a * b
code = func.__code__

print(dis.dis(func))
# for dis doc: https://docs.python.org/3/library/dis.html

#   3           0 RESUME                   0

#   4           2 LOAD_FAST                0 (a) # 取到stack顶, 这里0是co_varnames[0]
#               4 LOAD_FAST                1 (b) # 取到stack顶
#               6 BINARY_OP                5 (*) # stack顶两元素相加
#              10 RETURN_VALUE # 返回stack顶
# None

print(f'co_code: {code.co_code}') #  二进制code码
print(f'co_name: {code.co_name}') # 函数吗
print(f'co_filename: {code.co_filename}') # 所在文件名
print(f'co_lnotab: {code.co_lnotab}') # bytecode对应的源代码行数(二进制码)

print(f'co_flags: {code.co_flags}') # 控制PVM行为
print(f'co_stacksize: {code.co_stacksize}') # stacksize

print(f'co_argcount: {code.co_argcount}')
print(f'co_posonlyargcount: {code.co_posonlyargcount}') # positional only args
# 比如 f(a,b=3,/,*args,**kwargs) 这里前面两个必须positonal传
print(f'co_kwonlyargcount: {code.co_kwonlyargcount}') # keyword only args
# 比如 f(a,*,b=3,*args,**kwargs) 这里b必须keyword传

print(f'co_nlocals: {code.co_nlocals}') # allmost sizeof(co_varnames)

print(f'co_varnames: {code.co_varnames}') # 所有local var包括args
print(f'co_names: {code.co_names}') # 所有除了co_varnames/co_cellvars/co_freevars的
# 如 b = a.attr 这个 attr 放到c co_names 里
print(f'co_cellvars: {code.co_cellvars}') # variable还会在其他scope用到, 闭包相关
print(f'co_freevars: {code.co_freevars}') # variable从其他scope来, 闭包相关

print(f'co_consts: {code.co_consts}') # 函数出现的所有常量

Python Frame

# 和 code object 区别是记录当前func运行stack状态, 即栈机
# Frame 是一个栈结构,实现是用链表完成的
import inspect
from objprint import op

def func(a, b):
    frame = inspect.currentframe()
    op(frame, honor_existing=False, depth=2) # 打印
    return a + b

func(1,2)
# 以下是输出
<frame 0x7f955ebb4110
  .f_back = <frame 0x7f955dc69bc0 # 上一个frame(调用者所属的frame)
    .f_back = None,
    .f_builtins = { ... }, # 这个frame对应内置函数
    .f_code = <code 0x7f955eb40f30 ... >, # code object
    .f_globals = { ... }, # 全局变量
    .f_lasti = 48, # program counter 指现在运行到哪个字节码了
    .f_lineno = 10, # 现在运行到第几行了
    .f_locals = { ... }, # 局部变量
    .f_trace = None, # 如果不是None就有callback
    .f_trace_lines = True, # 是否每行trigger callback
    .f_trace_opcodes = False # 是否每个字节码trigger callback
  >,
posted @ 2023-11-18 00:59  xytpai  阅读(6)  评论(0编辑  收藏  举报