1. 程式人生 > >pycodeobject 與pyc 檔案

pycodeobject 與pyc 檔案

通常認為, 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 對應