1 def func(): 2 import sys 3 frame = sys._getframe() 4 frame0 = sys._getframe(0) 5 frame1 = sys._getframe(1) 6 7 print('1:',frame) 8 print('2:',frame0) 9 print('3:',frame1) 10 print('4:',frame.f_code) 11 print('5:',frame.f_locals) 12 print('6:',frame.f_globals) 13 print('7:',frame.f_back.f_locals) 14 print('8:',frame.f_code.co_filename) 15 print('9:',frame.f_code.co_name ) 16 #你可以打印frame的各个域 17 print('10:',frame0.f_code) 18 print('11:',frame0.f_locals) 19 print('12:',frame0.f_globals) 20 print('13:',frame0.f_code.co_filename) 21 print('14:',frame0.f_code.co_name ) 22 23 print('15:',frame1.f_code) 24 print('16:',frame1.f_locals) 25 print('17:',frame1.f_globals) 26 print('18:',frame1.f_code.co_filename) 27 print('19:',frame1.f_code.co_name ) 28 29 func()
1 1: <frame object at 0x000001F52F081108> 2 2: <frame object at 0x000001F52F081108> 3 3: <frame object at 0x000001F52F2B9828> 4 4: <code object func at 0x000001F52F725AE0, file "test.py", line 1> 5 5: {'frame1': <frame object at 0x000001F52F2B9828>, 'frame0': <frame object at 0x000001F52F081108>, 'frame': <frame object at 0x000001F52F081108>, 'sys': <module 'sys' (built-in)>} 6 6: {'__cached__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x000001F52F729A58>, '__name__': '__main__', '__builtins__': <module 'builtins' (built-in)>, '__doc__': None, '__file__': 'test.py', '__package__': None, '__spec__': None, 'func': <function func at 0x000001F52F936950>} 7 7: {'__cached__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x000001F52F729A58>, '__name__': '__main__', '__builtins__': <module 'builtins' (built-in)>, '__doc__': None, '__file__': 'test.py', '__package__': None, '__spec__': None, 'func': <function func at 0x000001F52F936950>} 8 8: test.py 9 9: func 10 10: <code object func at 0x000001F52F725AE0, file "test.py", line 1> 11 11: {'frame1': <frame object at 0x000001F52F2B9828>, 'frame0': <frame object at 0x000001F52F081108>, 'frame': <frame object at 0x000001F52F081108>, 'sys': <module 'sys' (built-in)>} 12 12: {'__cached__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x000001F52F729A58>, '__name__': '__main__', '__builtins__': <module 'builtins' (built-in)>, '__doc__': None, '__file__': 'test.py', '__package__': None, '__spec__': None, 'func': <function func at 0x000001F52F936950>} 13 13: test.py 14 14: func 15 15: <code object <module> at 0x000001F52F7626F0, file "test.py", line 1> 16 16: {'__cached__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x000001F52F729A58>, '__name__': '__main__', '__builtins__': <module 'builtins' (built-in)>, '__doc__': None, '__file__': 'test.py', '__package__': None, '__spec__': None, 'func': <function func at 0x000001F52F936950>} 17 17: {'__cached__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x000001F52F729A58>, '__name__': '__main__', '__builtins__': <module 'builtins' (built-in)>, '__doc__': None, '__file__': 'test.py', '__package__': None, '__spec__': None, 'func': <function func at 0x000001F52F936950>} 18 18: test.py 19 19: <module>
假如test.py用C语言来实现,会是下面这个样子:
- const char *s = “hello”;
- void func() {
- printf(“%s\n”, s);
- }
- int main() {
- func();
- return 0;
- }
Python虚拟机的原理就是模拟上述行为。当发生函数调用时,创建新的栈帧,对应Python的实现就是PyFrameObject对象。
7.1 PyFrameObject
- typedef struct _frame {
- PyObject_VAR_HEAD
- struct _frame *f_back; /* 调用者的帧 */
- PyCodeObject *f_code; /* 帧对应的字节码对象 */
- PyObject *f_builtins; /* 内置名字空间 */
- PyObject *f_globals; /* 全局名字空间 */
- PyObject *f_locals; /* 本地名字空间 */
- PyObject **f_valuestack; /* 运行时栈底 */
- PyObject **f_stacktop; /* 运行时栈顶 */
- …….
- }
那么对应Python的运行时栈就是这样子:
7.2 执行指令
执行test.py的字节码时,会先创建一个栈帧,以下用f表示当前栈帧,执行过程注释如下:
test.py的符号名集合和常量集合
- co.co_names (‘s’, ’func’)
- co.co_consts (‘hello’, <code object func at 0x2aaeeec57110, file ”test.py”, line 3>, None)
test.py的指令序列
上面的CALL_FUNCTION指令执行时,会创建新的栈帧,并执行func的字节码指令,以下用f表示当前栈帧,func的字节码执行过程如下:
func函数的符号名集合和常量集合
- func.co_names (‘s’,)
- func.co_consts (None,)
func函数的指令序列