1. Process Overview
Python first compiles the code (. py file) into bytecode, gives it to the bytecode virtual machine, and then executes the bytecode instruction by executing a byte-code command on the virtual machine to complete the execution of the program.
2. Byte code
The byte code corresponds to the Pycodeobject object in the Python virtual machine program.
The. PYc file is a representation of the bytecode on disk.
3. pyc file
The time when the Pycodeobject object is created is when the module is loaded, that is, import.
Python test.py compiles the test.py into bytecode and interprets execution, but does not generate TEST.PYC.
If test.py loads other modules, such as import Util,python compiles the util.py into bytecode, generates UTIL.PYC, and executes the bytecode interpretation.
If you want to generate TEST.PYC, we can use the Python built-in module Py_compile to compile.
When the module is loaded, if both. py and. Pyc,python try to use. PYC, if the. PYc is compiled earlier than the. Py modification time, recompile the. py and update. PYc.
4. Pycodeobject
The result of the Python code compilation is the Pycodeobject object.
typedef struct { pyobject_head int co_argcount; /* Number of positional parameters */ int co_nlocals; /* Number of local variables */ int co_stacksize; /* Stack size */ int co_flags; Pyobject *co_code; /* Byte code instruction sequence */ pyobject *co_consts; /* All constant Sets */ pyobject *co_names; /* All symbol names set */ pyobject *co_varnames; /* Local variable name collection */ pyobject *co_freevars; /* Variable name set for the closure of the packet */ pyobject *co_cellvars; /* The variable name set referenced by the inner nested function */ * The rest doesn ' t count for hash/cmp */ pyobject *co_filename; /* Code Name */ pyobject *co_name; /* Module name | function name | class name */ int co_firstlineno; /* The starting line number of the code block in the file */ pyobject *co_lnotab; /* Byte code instruction and line number correspondence */ void *co_zombieframe; /* for optimization only (see FRAMEOBJECT.C) */} Pycodeobject;
5. pyc file Format
When the module is loaded, the corresponding Pycodeobject object of the module is written to the. pyc file, in the following format:
6. Parsing byte code
6.1 parsing Pycodeobject
Python provides built-in functions compile can compile Python code and view Pycodeobject objects, as follows:
python code [test.py]
s = "Hello" def func (): print Sfunc ()
Compile the code in the Python interactive shell to get the Pycodeobject object:
Dir (CO) already lists the various domains of the CO and wants to see a domain directly in the terminal output:
Test.py's Pycodeobject
Co.co_argcount 0co.co_nlocals 0co.co_names (' s ', ' func ') co.co_varnames (' s ', ' func ') co.co_consts (' Hello ', <code object func at 0x2aaeeec57110, file "test.py", line 3>, None) Co.co_code ' d\x00\x00z\x00\ x00d\x01\x00\x84\x00\x00z\x01\x00e\x01\x00\x83\x00\x00\x01d\x02\x00s '
The Python interpreter will also generate the bytecode for the function Pycodeobject object, see above Co_consts[1]
Pycodeobject of the Func
Func.co_argcount 0func.co_nlocals 0func.co_names (' s ',) func.co_varnames () func.co_consts ( None,) func.co_code ' t\x00\x00ghd\x00\x00s '
Co_code is a sequence of instructions, a string of binary streams, and its format and parsing methods are shown in 6.2.
6.2 parsing instruction sequence
format of the instruction sequence Co_code
opcode |
Oparg |
opcode |
opcode |
Oparg |
... | ..
1 byte |
2 bytes |
1 byte |
1 byte |
2 bytes |
|
Python's built-in dis module can parse Co_code, such as:
test.py sequence of instructions
sequence of instructions for the Func function
The first column represents the line number of the following instructions in the Py file;
The second column is the offset of the instruction in the instruction sequence Co_code;
The third column is the name of the instruction opcode, which is divided into two types with operands and no operands, and opcode is a byte integer in the instruction sequence;
The fourth column is the operand oparg, which occupies two bytes in the instruction sequence, and is basically the subscript of the co_consts or co_names;
The fifth column with parentheses is the operand description.
7. Execute byte code
The principle of a Python virtual machine is to simulate an executable program and then X86 the machine, X86 the runtime stack frames such as:
If test.py is implemented in C, it will look like this:
Const char *s = "Hello"; void func () { printf ("%s\n", s);} int Main () { func (); return 0 ;}
The principle of Python virtual machines is to simulate these behaviors. When a function call occurs, a new stack frame is created, and the implementation of the python corresponds to the Pyframeobject object.
7.1 Pyframeobject
typedef struct _FRAME { pyobject_var_head struct _frame *f_back; /* Caller's Frame */ pycodeobject *f_code; /* byte-code object corresponding to frame */ pyobject *f_builtins; /* Built-in namespaces */ pyobject *f_globals; /* Global namespace */ pyobject *f_locals; /* Local namespace */ pyobject **f_valuestack; /* Run-time bottom */ pyobject **f_stacktop; /* run-time stack top */ ...}
So the runtime stack that corresponds to Python is like this:
7.2 Execution Instructions
When executing the test.py bytecode, a stack frame is created, with F representing the current stack frame, and the following process comments:
test.py set of symbolic names and constants
Co.co_names (' s ', ' func ') co.co_consts (' Hello ', <code object func at 0x2aaeeec57110, file "test.py", line 3 , None)
test.py sequence of instructions
When the above call_function instruction executes, a new stack frame is created and the func bytecode instruction is executed, and the following uses F for the current stack frame, and the Func bytecode is executed as follows:
a set of symbolic names and constants for the Func function
Func.co_names (' s ',) func.co_consts (None,)
sequence of instructions for the Func function
7.3 Viewing stack frames
If you want to view the current stack frame, Python provides the Sys._getframe () method to get the current stack frame, and you just need to include the code in the code as follows:
def func (): import sys frame = sys._getframe () print frame.f_locals print frame.f_globals print Frame.f_back.f_locals #你可以打印frame的各个域 print S
How Python programs are executed