通常认为, python 是一种解释性的语言,但是这种说法是不正确的,实际上,python在执
行时,首先会将.py 文件中的源代码编译成python的byte code(字节码), 然后再由python
virtual machine 来执行这些编译好的byte code。这种机制的基本思想跟java ,. NET 是一致的。
然而. python virtual machine 与java 或.net 的virtual machine 不同的是,python 的virtual
machine 是一种更高级的virtual machine, 这里的高级并不是通常意义上的高级,不是说python
的virtual machine 比java 或.net 的功能更强大,而是说,和java 或.net 相比,python 的virtual
machine 距离真实机器的距离更远。或者可以这么说,python 的virtual machine 是一种抽象
层次更高的virtual machine.
我们来考虑下面的pytho 代码:
class A:
pass
def fun():
pass
value = 1
str = "Python"
a = A()
Fun()
Python 在执行codeObject.py 时,首先需要进行的动作是对其进行编译,编译的结果是什么呢?
当然有字节码, 否则python 也就没有办法玩下去了,然而,除了字节码之外,还包含其他一
些结果,这些结果也是python 运行时所必需的,看一下我们上述的例子,从这个文件中,我
们可以看到,其中包括了一些字符串,一些常量值,还有一些操作,当然,python对操作的
处理结果就是字节码,那么python 的编译过程对字符串和常量的处理结果是什么呢?
实际上,这些在python源码中包含的静态信息都会被python 收集起来,编译的结果中包含了
字符串、常量值,字节码等等在源代码中出现的一切有用的 静态信息,而这些信息最终会存储
在python 运行期的一个对象中,当python 运行结束后,这些信息甚至还会被存储在一个文件中,
这个对象和文件就是我们这章探索的重点: pycodeobject 对象和pyc 文件。
/* Bytecode object */
typedef struct {
PyObject_HEAD
int co_argcount; /* #arguments, except *args */
int co_kwonlyargcount; /* #keyword only arguments */
int co_nlocals; /* #local variables */
int co_stacksize; /* #entries needed for evaluation stack */
int co_flags; /* CO_..., see below */
int co_firstlineno; /* first source line number */
PyObject *co_code; /* instruction opcodes */
PyObject *co_consts; /* list (constants used) */
PyObject *co_names; /* list of strings (names used) */
PyObject *co_varnames; /* tuple of strings (local variable names) */
PyObject *co_freevars; /* tuple of strings (free variable names) */
PyObject *co_cellvars; /* tuple of strings (cell variable names) */
/* The rest aren't used in either hash or comparisons, except for co_name,
used in both. This is done to preserve the name and line number
for tracebacks and debuggers; otherwise, constant de-duplication
would collapse identical functions/lambdas defined on different lines.
*/
Py_ssize_t *co_cell2arg; /* Maps cell vars which are arguments. */
PyObject *co_filename; /* unicode (where it was loaded from) */
PyObject *co_name; /* unicode (name, for reference) */
PyObject *co_lnotab; /* string (encoding addr<->lineno mapping) See
Objects/lnotab_notes.txt for details. */
void *co_zombieframe; /* for optimization only (see frameobject.c) */
PyObject *co_weakreflist; /* to support weakrefs to code objects */
/* Scratch space for extra data relating to the code object.
Type is a void* to keep the format private in codeobject.c to force
people to go through the proper APIs. */
void *co_extra;
} PyCodeObject;
可以说PyCodeObject 就是python 源代码编译之后关于程序的静态信息的集合。
在对python 源代码进行编译的时候,对于一段code (code block) , 会创建一个
pycodeobject 与这段code 对应