【Python】運(yùn)行環(huán)境初始化

0x01 線程環(huán)境初始化

線程模型回顧

Python啟動(dòng)后,真正有意義的初始化動(dòng)作是從Py_Initialize開始(當(dāng)然Py_Initialize之前也做了很多復(fù)雜的動(dòng)作)愈涩,Py_Initialize中調(diào)用了Py_InitializeEx秘豹。

// python.c -- Minimal main program -- everything is loaded from the library
int
main(int argc, char **argv)
{
    /* 754 requires that FP exceptions run in "no stop" mode by default,
     * and until C vendors implement C99's ways to control FP exceptions,
     * Python requires non-stop mode.  Alas, some platforms enable FP
     * exceptions by default.  Here we disable them.
     */
#ifdef __FreeBSD__
    fp_except_t m;

    m = fpgetmask();
    fpsetmask(m & ~FP_X_OFL);
#endif
    return Py_Main(argc, argv);
}

// main.c -- Python interpreter main program
/* Main program */
int
Py_Main(int argc, char **argv)
{
    ......
    Py_Initialize
    ......
}

//Pythonrun.c
void
Py_Initialize(void)
{
    Py_InitializeEx(1);
}

void
Py_InitializeEx(int install_sigs)
{
    PyInterpreterState *interp;
    PyThreadState *tstate;
    PyObject *bimod, *sysmod;
    char *p;

    extern void _Py_ReadyTypes(void);

    if (initialized)
        return;
    initialized = 1;

    if ((p = Py_GETENV("PYTHONDEBUG")) && *p != '\0')
        Py_DebugFlag = add_flag(Py_DebugFlag, p);
    if ((p = Py_GETENV("PYTHONVERBOSE")) && *p != '\0')
        Py_VerboseFlag = add_flag(Py_VerboseFlag, p);
    if ((p = Py_GETENV("PYTHONOPTIMIZE")) && *p != '\0')
        Py_OptimizeFlag = add_flag(Py_OptimizeFlag, p);
    // 創(chuàng)建進(jìn)程狀態(tài)
    interp = PyInterpreterState_New();
    if (interp == NULL)
        Py_FatalError("Py_Initialize: can't make first interpreter");
    // 創(chuàng)建線程狀態(tài)
    tstate = PyThreadState_New(interp);
    if (tstate == NULL)
        Py_FatalError("Py_Initialize: can't make first thread");
    (void) PyThreadState_Swap(tstate);
    // 初始化類型模型
    _Py_ReadyTypes();

    if (!_PyFrame_Init())
        Py_FatalError("Py_Initialize: can't init frames");

    if (!_PyInt_Init())
        Py_FatalError("Py_Initialize: can't init ints");

    _PyFloat_Init();
    // 初始化modules
    interp->modules = PyDict_New();
    if (interp->modules == NULL)
        Py_FatalError("Py_Initialize: can't make modules dictionary");
    interp->modules_reloading = PyDict_New();
    if (interp->modules_reloading == NULL)
        Py_FatalError("Py_Initialize: can't make modules_reloading dictionary");
    // 初始化__built__ module
    bimod = _PyBuiltin_Init();
    if (bimod == NULL)
        Py_FatalError("Py_Initialize: can't initialize __builtin__");
    interp->builtins = PyModule_GetDict(bimod);
    if (interp->builtins == NULL)
        Py_FatalError("Py_Initialize: can't initialize builtins dict");
    Py_INCREF(interp->builtins);
    // 初始化sys module
    sysmod = _PySys_Init();
    if (sysmod == NULL)
        Py_FatalError("Py_Initialize: can't initialize sys");
    interp->sysdict = PyModule_GetDict(sysmod);
    if (interp->sysdict == NULL)
        Py_FatalError("Py_Initialize: can't initialize sys dict");
    Py_INCREF(interp->sysdict);
    _PyImport_FixupExtension("sys", "sys");
    // 設(shè)置module搜索路徑集合
    PySys_SetPath(Py_GetPath());
    // 設(shè)置了sys.modules枫振,他就是interp->modules
    PyDict_SetItemString(interp->sysdict, "modules",
                 interp->modules);
    // 初始化import機(jī)制的環(huán)境
    _PyImport_Init();

    /* initialize builtin exceptions */
    // 初始化Python內(nèi)建的exceptions
    _PyExc_Init();
    // 備份exceptions module 和 __builtin__ module
    _PyImport_FixupExtension("exceptions", "exceptions");
    /* phase 2 of builtins */
    _PyImport_FixupExtension("__builtin__", "__builtin__");
    // 在sys module中添加一些對(duì)象蚀乔,用于import機(jī)制
    _PyImportHooks_Init();

    if (install_sigs)
        initsigs(); /* Signal handling stuff, including initintr() */

    initmain(); /* Module __main__ */
    if (!Py_NoSiteFlag)
        initsite(); /* Module site */

    warnings_module = PyImport_ImportModule("warnings");
    if (!warnings_module)
        PyErr_Clear();
}

Py_InitializeEx中完成了一個(gè)重要工作就是加載多個(gè)基礎(chǔ)的module__builtin__sys等)源梭,還會(huì)完成Python類型系統(tǒng)的初始化和異常系統(tǒng)初始化娱俺。

// pystate.h
typedef struct _is {

    struct _is *next;
    struct _ts *tstate_head;    // 模擬進(jìn)程環(huán)境中的線程集合
    PyObject *modules;
    PyObject *sysdict;
    PyObject *builtins;
    PyObject *modules_reloading;

    PyObject *codec_search_path;
    PyObject *codec_search_cache;
    PyObject *codec_error_registry;
} PyInterpreterState;

typedef struct _ts {
    struct _ts *next;
    PyInterpreterState *interp;

    struct _frame *frame;    // 模擬線程中的函數(shù)調(diào)用堆棧
    int recursion_depth;
    int tracing;
    int use_tracing;

    Py_tracefunc c_profilefunc;
    Py_tracefunc c_tracefunc;
    PyObject *c_profileobj;
    PyObject *c_traceobj;

    PyObject *curexc_type;
    PyObject *curexc_value;
    PyObject *curexc_traceback;

    PyObject *exc_type;
    PyObject *exc_value;
    PyObject *exc_traceback;

    PyObject *dict;  /* Stores per-thread state */

    int tick_counter;

    int gilstate_counter;

    PyObject *async_exc; /* Asynchronous exception to raise */
    long thread_id; /* Thread id where this tstate was created */

    int trash_delete_nesting;
    PyObject *trash_delete_later;
} PyThreadState;
某時(shí)刻Python運(yùn)行時(shí)的整個(gè)環(huán)境

初始化線程環(huán)境

win32環(huán)境,當(dāng)執(zhí)行一個(gè)可執(zhí)行文件時(shí)废麻,操作系統(tǒng)首先會(huì)創(chuàng)建一個(gè)進(jìn)程內(nèi)核對(duì)象矢否。同樣,在Python中也是如此脑溢,在Py_InitializeEx的開始處僵朗,Python會(huì)首先調(diào)用PyInterpreterState_New創(chuàng)建一個(gè)嶄新的PyInterpreterState對(duì)象。

// pystate.c
static PyInterpreterState *interp_head = NULL;

PyInterpreterState *
PyInterpreterState_New(void)
{
    PyInterpreterState *interp = (PyInterpreterState *)
                     malloc(sizeof(PyInterpreterState));

    if (interp != NULL) {
        HEAD_INIT();
#ifdef WITH_THREAD
        if (head_mutex == NULL)
            Py_FatalError("Can't initialize threads for interpreter");
#endif
        interp->modules = NULL;
        interp->modules_reloading = NULL;
        interp->sysdict = NULL;
        interp->builtins = NULL;
        interp->tstate_head = NULL;
        interp->codec_search_path = NULL;
        interp->codec_search_cache = NULL;
        interp->codec_error_registry = NULL;

        HEAD_LOCK();
        interp->next = interp_head;
        interp_head = interp;
        HEAD_UNLOCK();
    }
    return interp;
}

Python的運(yùn)行時(shí)環(huán)境中屑彻,有一個(gè)全局變量interp_head(一個(gè)PyInterpreterState鏈表)來管理PyInterpreterState對(duì)象验庙,在Python運(yùn)行時(shí)可能會(huì)有多個(gè)PyInterpreterState對(duì)象鏈接在一起(這個(gè)就是對(duì)操作系統(tǒng)多進(jìn)程的模擬)。新創(chuàng)建的PyInterpreterState對(duì)象如下所示:

新創(chuàng)建的PyInterpreterState對(duì)象

在創(chuàng)建了PyInterpreterState進(jìn)程狀態(tài))對(duì)象之后社牲,Python會(huì)調(diào)用PyThreadState_New函數(shù)來創(chuàng)建PyThreadState線程狀態(tài))對(duì)象粪薛。

// pystate.c
PyThreadState *
PyThreadState_New(PyInterpreterState *interp)
{
    PyThreadState *tstate = (PyThreadState *)malloc(sizeof(PyThreadState));
    // 設(shè)置獲得線程中函數(shù)調(diào)用棧的操作
    if (_PyThreadState_GetFrame == NULL)
        _PyThreadState_GetFrame = threadstate_getframe;

    if (tstate != NULL) {
        // 在PyThreadState對(duì)象中關(guān)聯(lián)PyInterpreterState對(duì)象
        tstate->interp = interp;

        tstate->frame = NULL;
        tstate->recursion_depth = 0;
        tstate->tracing = 0;
        tstate->use_tracing = 0;
        tstate->tick_counter = 0;
        tstate->gilstate_counter = 0;
        tstate->async_exc = NULL;

        tstate->dict = NULL;

        tstate->curexc_type = NULL;
        tstate->curexc_value = NULL;
        tstate->curexc_traceback = NULL;

        tstate->exc_type = NULL;
        tstate->exc_value = NULL;
        tstate->exc_traceback = NULL;

        tstate->c_profilefunc = NULL;
        tstate->c_tracefunc = NULL;
        tstate->c_profileobj = NULL;
        tstate->c_traceobj = NULL;

        HEAD_LOCK();
        tstate->next = interp->tstate_head;
        // 在PyInterpreterState對(duì)象中關(guān)聯(lián)PyThreadState對(duì)象
        interp->tstate_head = tstate;
        HEAD_UNLOCK();
    }

    return tstate;
}

PyThreadState結(jié)構(gòu)體中也存在一個(gè)next指針,PyThreadStatePython運(yùn)行時(shí)也會(huì)創(chuàng)建一個(gè)鏈表(模擬多線程)搏恤。

還會(huì)設(shè)置從線程中獲得函數(shù)調(diào)用棧PyFrameObject對(duì)象鏈表)的方法(threadstate_getframe)违寿。

然后建立PyThreadState對(duì)象和PyInterpreterState對(duì)象的關(guān)系,結(jié)果如下所示:

PyThreadState對(duì)象和PyInterpreterState對(duì)象的關(guān)系圖示

Python的運(yùn)行時(shí)環(huán)境中熟空,有一個(gè)全局變量_PyThreadState_Current_PyThreadState_Current維護(hù)了當(dāng)前活動(dòng)的線程藤巢,更準(zhǔn)確的說是當(dāng)前活動(dòng)線程對(duì)應(yīng)的PyThreadState對(duì)象),初始化時(shí)該變量為NULL息罗。創(chuàng)建完PyThreadState對(duì)象后掂咒,會(huì)通過PyThreadState_Swap函數(shù)設(shè)置_PyThreadState_Current的值。

// pystate.c
PyThreadState * PyThreadState_Swap(PyThreadState *newts)
{
    PyThreadState *oldts = _PyThreadState_Current;
    _PyThreadState_Current = newts;
    return oldts;
}

接下來會(huì)通過_Py_ReadyTypes函數(shù)初始化Python類型系統(tǒng)(參考類機(jī)制剖析)迈喉。

然后通過_PyFrame_Init函數(shù)設(shè)置全局變量builtin_object绍刮。

// pystate.c
static PyObject *builtin_object;

int _PyFrame_Init()
{
    builtin_object = PyString_InternFromString("__builtins__");
    return (builtin_object != NULL);
}

這個(gè)內(nèi)容為__builtins__PyStringObject對(duì)象builtin_objectPyFrame_New創(chuàng)建一個(gè)新的PyFrameObject對(duì)象時(shí)會(huì)發(fā)揮作用。

接下來會(huì)初始化一些邊邊角角的東西挨摸。

至此孩革,Py_InitializeEx有了一個(gè)階段性結(jié)果,創(chuàng)建了代表進(jìn)程和線程的PyInterpreterStatePyThreadState對(duì)象得运,并且在他們之間建立了聯(lián)系膝蜈。接下來會(huì)進(jìn)入相對(duì)獨(dú)立的環(huán)節(jié):設(shè)置系統(tǒng)module

0x02 系統(tǒng)module初始化

創(chuàng)建__builtin__ module

Py_INitializeEx中澈圈,當(dāng)Python創(chuàng)建了PyThreadStatePyInterpreterState對(duì)象之后彬檀,就會(huì)開始通過_PyBuiltin_Init來設(shè)置系統(tǒng)的__builtin__ module了。在調(diào)用_PyBuiltin_Init之前瞬女,Python會(huì)通過interp->modules創(chuàng)建為一個(gè)PyDictObject對(duì)象,這個(gè)對(duì)象中維護(hù)著所有的PyThreadState對(duì)象共享的資源努潘。

// Bltinmodule.c
PyObject *
_PyBuiltin_Init(void)
{
    PyObject *mod, *dict, *debug;
    // 創(chuàng)建并設(shè)置__builtin__ module
    mod = Py_InitModule4("__builtin__", builtin_methods,
                 builtin_doc, (PyObject *)NULL,
                 PYTHON_API_VERSION);
    if (mod == NULL)
        return NULL;
    // 將所有內(nèi)建類型加到__builtin__ module中
    dict = PyModule_GetDict(mod);
        #ifdef Py_TRACE_REFS
    /* __builtin__ exposes a number of statically allocated objects
     * that, before this code was added in 2.3, never showed up in
     * the list of "all objects" maintained by Py_TRACE_REFS.  As a
     * result, programs leaking references to None and False (etc)
     * couldn't be diagnosed by examining sys.getobjects(0).
     */
#define ADD_TO_ALL(OBJECT) _Py_AddToAllObjects((PyObject *)(OBJECT), 0)
#else
#define ADD_TO_ALL(OBJECT) (void)0
#endif

#define SETBUILTIN(NAME, OBJECT) \
    if (PyDict_SetItemString(dict, NAME, (PyObject *)OBJECT) < 0)   \
        return NULL;                        \
    ADD_TO_ALL(OBJECT)

    SETBUILTIN("None",      Py_None);
    SETBUILTIN("Ellipsis",      Py_Ellipsis);
    SETBUILTIN("NotImplemented",    Py_NotImplemented);
    SETBUILTIN("False",     Py_False);
    SETBUILTIN("True",      Py_True);
    SETBUILTIN("basestring",    &PyBaseString_Type);
    SETBUILTIN("bool",      &PyBool_Type);
    SETBUILTIN("buffer",        &PyBuffer_Type);
    SETBUILTIN("classmethod",   &PyClassMethod_Type);
#ifndef WITHOUT_COMPLEX
    SETBUILTIN("complex",       &PyComplex_Type);
#endif
    SETBUILTIN("dict",      &PyDict_Type);
    SETBUILTIN("enumerate",     &PyEnum_Type);
    SETBUILTIN("file",      &PyFile_Type);
    SETBUILTIN("float",     &PyFloat_Type);
    SETBUILTIN("frozenset",     &PyFrozenSet_Type);
    SETBUILTIN("property",      &PyProperty_Type);
    SETBUILTIN("int",       &PyInt_Type);
    SETBUILTIN("list",      &PyList_Type);
    SETBUILTIN("long",      &PyLong_Type);
    SETBUILTIN("object",        &PyBaseObject_Type);
    SETBUILTIN("reversed",      &PyReversed_Type);
    SETBUILTIN("set",       &PySet_Type);
    SETBUILTIN("slice",     &PySlice_Type);
    SETBUILTIN("staticmethod",  &PyStaticMethod_Type);
    SETBUILTIN("str",       &PyString_Type);
    SETBUILTIN("super",     &PySuper_Type);
    SETBUILTIN("tuple",     &PyTuple_Type);
    SETBUILTIN("type",      &PyType_Type);
    SETBUILTIN("xrange",        &PyRange_Type);
#ifdef Py_USING_UNICODE
    SETBUILTIN("unicode",       &PyUnicode_Type);
#endif
    debug = PyBool_FromLong(Py_OptimizeFlag == 0);
    if (PyDict_SetItemString(dict, "__debug__", debug) < 0) {
        Py_XDECREF(debug);
        return NULL;
    }
    Py_XDECREF(debug);

    return mod;
#undef ADD_TO_ALL
#undef SETBUILTIN
}

整個(gè)函數(shù)的功能就是設(shè)置好__builtin__ module诽偷±ぱВ總共分為兩個(gè)步驟:

  • 創(chuàng)建PyModuleObject對(duì)象,在Python中报慕,module正是通過和這個(gè)對(duì)象來設(shè)置的
  • 設(shè)置module深浮,將Python中的所有的類型對(duì)象全塞進(jìn)新創(chuàng)建的__builtin__ module中。

在第一步中已經(jīng)設(shè)置好了大部分的內(nèi)容眠冈,由函數(shù)Py_InitModule4實(shí)現(xiàn):

// modsupport.c
PyObject *
Py_InitModule4(const char *name, PyMethodDef *methods, const char *doc,
           PyObject *passthrough, int module_api_version)
{
    PyObject *m, *d, *v, *n;
    PyMethodDef *ml;
    ......
    // 創(chuàng)建module對(duì)象
    if ((m = PyImport_AddModule(name)) == NULL)
        return NULL;
    // 設(shè)置module中的(符號(hào)飞苇,值)對(duì)應(yīng)關(guān)系
    d = PyModule_GetDict(m);
    if (methods != NULL) {
        n = PyString_FromString(name);
        if (n == NULL)
            return NULL;
        // 遍歷methods指定的module對(duì)象中應(yīng)該包含的操作集合
        for (ml = methods; ml->ml_name != NULL; ml++) {
            if ((ml->ml_flags & METH_CLASS) ||
                (ml->ml_flags & METH_STATIC)) {
                PyErr_SetString(PyExc_ValueError,
                        "module functions cannot set"
                        " METH_CLASS or METH_STATIC");
                Py_DECREF(n);
                return NULL;
            }
            v = PyCFunction_NewEx(ml, passthrough, n);
            if (v == NULL) {
                Py_DECREF(n);
                return NULL;
            }
            if (PyDict_SetItemString(d, ml->ml_name, v) != 0) {
                Py_DECREF(v);
                Py_DECREF(n);
                return NULL;
            }
            Py_DECREF(v);
        }
        Py_DECREF(n);
    }
    if (doc != NULL) {
        v = PyString_FromString(doc);
        if (v == NULL || PyDict_SetItemString(d, "__doc__", v) != 0) {
            Py_XDECREF(v);
            return NULL;
        }
        Py_DECREF(v);
    }
    return m;
}

Py_InitModule4參數(shù)的含義:

  • namemodule的名稱,在這里是__builtin__
  • methods:該module中所包含的函數(shù)的集合蜗顽,在這里是builtin_methods
  • docmodule的文檔厕宗,在這里是builtin_doc
  • passthrough:這個(gè)參數(shù)在Python 2.5中沒有使用似扔,為NULL
  • module_api_versionPython內(nèi)部使用的version值,用于比較

Py_InitModule4函數(shù)可以分為2個(gè)獨(dú)立的部分:創(chuàng)建module對(duì)象;將(符號(hào)旭咽,值)對(duì)應(yīng)關(guān)系放置到module中。

創(chuàng)建module對(duì)象

// import.c
PyObject *
PyImport_AddModule(const char *name)
{
    // 獲得Python維護(hù)的module集合
    PyObject *modules = PyImport_GetModuleDict();
    PyObject *m;
    // 如果module集合中沒有名為name的module對(duì)象串塑,就創(chuàng)建它舰讹,否則直接返回
    if ((m = PyDict_GetItemString(modules, name)) != NULL &&
        PyModule_Check(m))
        return m;
    m = PyModule_New(name);
    if (m == NULL)
        return NULL;
    // 將創(chuàng)建的module對(duì)象放入Python的全局module集合中
    if (PyDict_SetItemString(modules, name, m) != 0) {
        Py_DECREF(m);
        return NULL;
    }
    Py_DECREF(m); /* Yes, it still exists, in modules! */
    return m;
}

Python中維護(hù)了一個(gè)存放所有加載到內(nèi)存中的module集合,在這個(gè)集合中狸相,存放著所有的(module名薛匪,module對(duì)象)這樣的對(duì)應(yīng)關(guān)系,對(duì)應(yīng)到Python中就是sys.modules脓鹃。在創(chuàng)建一個(gè)新的module對(duì)象之前蛋辈,會(huì)先到這個(gè)全局module中查看是否已經(jīng)存在。通過PyImport_GetModuleDict函數(shù)獲得PyInterpreterState(進(jìn)程狀態(tài))對(duì)象中的module域的值将谊。

如果全局modules字典中沒有存在該namemodule對(duì)象冷溶,則通過PyModule_New函數(shù)創(chuàng)建一個(gè)新的module對(duì)象,然后將(name尊浓,module)對(duì)應(yīng)關(guān)系插入到modules集合中逞频。

// moduleobject.c
typedef struct {
    PyObject_HEAD
    PyObject *md_dict;
} PyModuleObject;

PyObject * PyModule_New(const char *name)
{
    PyModuleObject *m;
    PyObject *nameobj;
    m = PyObject_GC_New(PyModuleObject, &PyModule_Type);
    if (m == NULL)
        return NULL;
    nameobj = PyString_FromString(name);
    m->md_dict = PyDict_New();
    if (m->md_dict == NULL || nameobj == NULL)
        goto fail;
    if (PyDict_SetItemString(m->md_dict, "__name__", nameobj) != 0)
        goto fail;
    if (PyDict_SetItemString(m->md_dict, "__doc__", Py_None) != 0)
        goto fail;
    Py_DECREF(nameobj);
    PyObject_GC_Track(m);
    return (PyObject *)m;

 fail:
    Py_XDECREF(nameobj);
    Py_DECREF(m);
    return NULL;
}

實(shí)際上,PyModuleObject對(duì)象就是對(duì)PyDictObject對(duì)象的簡(jiǎn)單包裝栋齿,創(chuàng)建PyModuleObject對(duì)象的動(dòng)作很簡(jiǎn)單苗胀,注意在這里設(shè)置了module__name__屬性,但是沒有設(shè)置其__doc__屬性瓦堵。

至此基协,創(chuàng)建的PyModuleObject對(duì)象還算是空的,接下來就開始設(shè)置module對(duì)象菇用。

設(shè)置module對(duì)象

設(shè)置module對(duì)象的流程回到Py_InitModule4函數(shù)中澜驮,設(shè)置屬性主要依賴Py_InitModule4函數(shù)的第二個(gè)參數(shù)(methods),在這里為builtin_methods惋鸥,遍歷builtin_methods杂穷,處理其中的每一個(gè)元素悍缠。

// methodobject.h
typedef PyObject *(*PyCFunction)(PyObject *, PyObject *);
struct PyMethodDef {
    const char  *ml_name;   /* The name of the built-in function/method */
    PyCFunction  ml_meth;   /* The C function that implements it */
    int      ml_flags;  /* Combination of METH_xxx flags, which mostly
                   describe the args expected by the C func */
    const char  *ml_doc;    /* The __doc__ attribute, or NULL */
};
typedef struct PyMethodDef PyMethodDef;

// bltinmodule.c
static PyMethodDef builtin_methods[] = {
    {"__import__",  (PyCFunction)builtin___import__, METH_VARARGS | METH_KEYWORDS, import_doc},
    {"abs",     builtin_abs,        METH_O, abs_doc},
    {"all",     builtin_all,        METH_O, all_doc},
    {"any",     builtin_any,        METH_O, any_doc},
    {"apply",   builtin_apply,      METH_VARARGS, apply_doc},
    {"callable",    builtin_callable,   METH_O, callable_doc},
    {"chr",     builtin_chr,        METH_VARARGS, chr_doc},
    {"cmp",     builtin_cmp,        METH_VARARGS, cmp_doc},
    {"coerce",  builtin_coerce,     METH_VARARGS, coerce_doc},
    {"compile", builtin_compile,    METH_VARARGS, compile_doc},
    {"delattr", builtin_delattr,    METH_VARARGS, delattr_doc},
    {"dir",     builtin_dir,        METH_VARARGS, dir_doc},
    {"divmod",  builtin_divmod,     METH_VARARGS, divmod_doc},
    {"eval",    builtin_eval,       METH_VARARGS, eval_doc},
    {"execfile",    builtin_execfile,   METH_VARARGS, execfile_doc},
    {"filter",  builtin_filter,     METH_VARARGS, filter_doc},
    {"getattr", builtin_getattr,    METH_VARARGS, getattr_doc},
    {"globals", (PyCFunction)builtin_globals,    METH_NOARGS, globals_doc},
    {"hasattr", builtin_hasattr,    METH_VARARGS, hasattr_doc},
    {"hash",    builtin_hash,       METH_O, hash_doc},
    {"hex",     builtin_hex,        METH_O, hex_doc},
    {"id",      builtin_id,         METH_O, id_doc},
    {"input",   builtin_input,      METH_VARARGS, input_doc},
    {"intern",  builtin_intern,     METH_VARARGS, intern_doc},
    {"isinstance",  builtin_isinstance, METH_VARARGS, isinstance_doc},
    {"issubclass",  builtin_issubclass, METH_VARARGS, issubclass_doc},
    {"iter",    builtin_iter,       METH_VARARGS, iter_doc},
    {"len",     builtin_len,        METH_O, len_doc},
    {"locals",  (PyCFunction)builtin_locals,     METH_NOARGS, locals_doc},
    {"map",     builtin_map,        METH_VARARGS, map_doc},
    {"max",     (PyCFunction)builtin_max,        METH_VARARGS | METH_KEYWORDS, max_doc},
    {"min",     (PyCFunction)builtin_min,        METH_VARARGS | METH_KEYWORDS, min_doc},
    {"oct",     builtin_oct,        METH_O, oct_doc},
    {"open",    (PyCFunction)builtin_open,       METH_VARARGS | METH_KEYWORDS, open_doc},
    {"ord",     builtin_ord,        METH_O, ord_doc},
    {"pow",     builtin_pow,        METH_VARARGS, pow_doc},
    {"range",   builtin_range,      METH_VARARGS, range_doc},
    {"raw_input",   builtin_raw_input,  METH_VARARGS, raw_input_doc},
    {"reduce",  builtin_reduce,     METH_VARARGS, reduce_doc},
    {"reload",  builtin_reload,     METH_O, reload_doc},
    {"repr",    builtin_repr,       METH_O, repr_doc},
    {"round",   (PyCFunction)builtin_round,      METH_VARARGS | METH_KEYWORDS, round_doc},
    {"setattr", builtin_setattr,    METH_VARARGS, setattr_doc},
    {"sorted",  (PyCFunction)builtin_sorted,     METH_VARARGS | METH_KEYWORDS, sorted_doc},
    {"sum",     builtin_sum,        METH_VARARGS, sum_doc},
#ifdef Py_USING_UNICODE
    {"unichr",  builtin_unichr,     METH_VARARGS, unichr_doc},
#endif
    {"vars",    builtin_vars,       METH_VARARGS, vars_doc},
    {"zip",         builtin_zip,        METH_VARARGS, zip_doc},
    {NULL,      NULL},
};
len函數(shù)對(duì)應(yīng)的PyMethodDef結(jié)構(gòu)

對(duì)于builtin_methods中的每一個(gè)PyMethodDef結(jié)構(gòu),PyInitModule4都會(huì)基于它創(chuàng)建一個(gè)PyCFunctionObject對(duì)象(Python中對(duì)函數(shù)指針的包裝)耐量。

// methodobject.h
typedef struct {
    PyObject_HEAD
    PyMethodDef *m_ml; /* Description of the C function to call */
    PyObject    *m_self; /* Passed as 'self' arg to the C func, can be NULL */
    PyObject    *m_module; /* The __module__ attribute, can be anything */
} PyCFunctionObject;

// methodobject.c
PyObject *
PyCFunction_NewEx(PyMethodDef *ml, PyObject *self, PyObject *module)
{
    PyCFunctionObject *op;
    op = free_list;
    if (op != NULL) {
        free_list = (PyCFunctionObject *)(op->m_self);
        PyObject_INIT(op, &PyCFunction_Type);
    }
    else {
        op = PyObject_GC_New(PyCFunctionObject, &PyCFunction_Type);
        if (op == NULL)
            return NULL;
    }
    op->m_ml = ml;
    Py_XINCREF(self);
    op->m_self = self;
    Py_XINCREF(module);
    op->m_module = module;
    _PyObject_GC_TRACK(op);
    return (PyObject *)op;
}

PyCFunctionObject對(duì)象中的那個(gè)self飞蚓,也就是在Py_InitModule4中傳入的passthrough(之前說這個(gè)參數(shù)在Python 2.5中沒用,所以這里的self也就為NULL)廊蜒。

注意趴拧,PyCFunctionObject對(duì)象中的m_module域并不是指向一個(gè)真正的PyModuleObject對(duì)象,而是一個(gè)PyStringObject對(duì)象山叮,但是這個(gè)PyStringObject對(duì)象正是PyModuleObject對(duì)象的名字(根據(jù)PyModuleObject對(duì)象的名字可以在全局modules中找到對(duì)應(yīng)的PyModuleObject對(duì)象)著榴。

創(chuàng)建完成的 __builtin__ module

__builtin__ module創(chuàng)建完以后,也就是bimod = _PyBuiltin_Init()執(zhí)行完以后聘芜,將PyModuleObject對(duì)象中維護(hù)的那個(gè)PyDictObject對(duì)象賦值給interp->builtins兄渺。以后Python在需要訪問__builtin__ module時(shí),直接訪問interp->builtins就行汰现,不需要再到interp->modules中去找到__builtin__ module對(duì)象然后再去訪問挂谍。因?yàn)?code>Python中使用__builtin__ module非常頻繁,這樣的機(jī)制會(huì)速度會(huì)更快瞎饲。

創(chuàng)建sys module

sys module的備份

Python在創(chuàng)建并設(shè)置了__builtin__ module之后口叙,會(huì)類似的以同樣流程設(shè)置sys module,并像設(shè)置interp->builtins一樣設(shè)置interp->sysdict嗅战。

設(shè)置完成__builtin__sys兩個(gè)module之后妄田,PyInterpreterStatePyThreadState對(duì)象在內(nèi)存中的情形如下所示:

此時(shí)內(nèi)存中情形

由于Pythonmodule集合interp->modules是一個(gè)PyDictObject對(duì)象,而PyDictObject對(duì)象在Python中是一個(gè)可變對(duì)象(其中維護(hù)的(module name驮捍,PyModuleObject)元素對(duì)在運(yùn)行時(shí)有可能被刪除)疟呐。

對(duì)于Python的擴(kuò)展modulesys等),為了避免被刪除后的重新初始化东且,Python會(huì)將所有的擴(kuò)展module通過一個(gè)全局PyDictObject對(duì)象來進(jìn)行備份維護(hù)启具,這里通過_PyImport_FixupExtension("sys", "sys")函數(shù)完成:

// import.c
static PyObject *extensions = NULL;

PyObject *
_PyImport_FixupExtension(char *name, char *filename)
{
    PyObject *modules, *mod, *dict, *copy;
    // 如果extensions為空,則創(chuàng)建PyDictObject對(duì)象賦給extensions
    if (extensions == NULL) {
        extensions = PyDict_New();
        if (extensions == NULL)
            return NULL;
    }
    // 獲得進(jìn)程對(duì)象的modules集合珊泳,interp->modules
    modules = PyImport_GetModuleDict();
        // 在interp->modules中找到名字為name的module
    mod = PyDict_GetItemString(modules, name);
    if (mod == NULL || !PyModule_Check(mod)) {
        PyErr_Format(PyExc_SystemError,
          "_PyImport_FixupExtension: module %.200s not loaded", name);
        return NULL;
    }
    // 抽取module中的dict
    dict = PyModule_GetDict(mod);
    if (dict == NULL)
        return NULL;
    // 對(duì)dict進(jìn)行拷貝
    copy = PyDict_Copy(dict);
    if (copy == NULL)
        return NULL;
    // 將拷貝得到的心dict存儲(chǔ)在extensions中
    PyDict_SetItemString(extensions, filename, copy);
    Py_DECREF(copy);
    return copy;
}

上面代碼介紹了備份的過程鲁冯,第一次會(huì)創(chuàng)建一個(gè)新的PyDictObject對(duì)象,這個(gè)對(duì)象將維護(hù)所有已經(jīng)被Python加載的module中的PyDictObject的一個(gè)佩芬色查。當(dāng)系統(tǒng)中的modules集合中的某個(gè)標(biāo)準(zhǔn)擴(kuò)展module被刪除后又被重新加載時(shí)薯演,Python就不需要再次初始化這些module,只需extensions中備份的PyDictObject對(duì)象來創(chuàng)建一個(gè)新的module即可秧了。

設(shè)置module搜索路徑

在創(chuàng)建完sys module以后跨扮,會(huì)在此module中設(shè)置Python搜索一個(gè)module時(shí)的默認(rèn)搜索路徑集合(PySys_SetPath(Py_GetPath()))。這個(gè)路徑集合就是在Python執(zhí)行import xyz時(shí)將查看的路徑的集合。

// sysmodule.c
void
PySys_SetPath(char *path)
{
    PyObject *v;
    if ((v = makepathobject(path, DELIM)) == NULL)
        Py_FatalError("can't create sys.path");
    if (PySys_SetObject("path", v) != 0)
        Py_FatalError("can't assign sys.path");
    Py_DECREF(v);
}

int
PySys_SetObject(char *name, PyObject *v)
{
    PyThreadState *tstate = PyThreadState_GET();
    PyObject *sd = tstate->interp->sysdict;
    if (v == NULL) {
        if (PyDict_GetItemString(sd, name) == NULL)
            return 0;
        else
            return PyDict_DelItemString(sd, name);
    }
    else
        return PyDict_SetItemString(sd, name, v);
}

makepathobject中會(huì)創(chuàng)建一個(gè)PyListObject對(duì)象好港,這個(gè)PyListObject對(duì)象中包含一組PyStringObject對(duì)象愉镰,每一個(gè)PyStringObject對(duì)象的內(nèi)容就是一個(gè)module的搜索路徑(也就是Python中的sys.path)米罚。

最終钧汹,這個(gè)代表搜索路徑集合的list對(duì)象會(huì)在PySys_SetObject中被插入到interp->sysdict這個(gè)PyDictObject對(duì)象(sys module中維護(hù)的那個(gè)PyDictObject對(duì)象)中。

接下來录择,Python會(huì)進(jìn)行一些瑣碎的動(dòng)作拔莱,其中包含初始化Pythonimport環(huán)境,初始化Python的內(nèi)建異常(其實(shí)就是調(diào)用PyType_Ready初始化各個(gè)異常類)隘竭。

創(chuàng)建__main__ module

_PyImportHooks_Init之后塘秦,Python會(huì)創(chuàng)建一個(gè)非常特殊的module__main__module

// pythonrun.c
/* Create __main__ module */
static void
initmain(void)
{
    PyObject *m, *d;
    // 創(chuàng)建__main__ module动看,并設(shè)置到interp->modules中
    m = PyImport_AddModule("__main__");
    if (m == NULL)
        Py_FatalError("can't create __main__ module");
    // 獲得__main__ module中的dict
    d = PyModule_GetDict(m);
    if (PyDict_GetItemString(d, "__builtins__") == NULL) {
        // 獲得interp->modules中的__builtin__ module 
        PyObject *bimod = PyImport_ImportModule("__builtin__");
        if (bimod == NULL ||
            // 將(“__builtins__”, __builtin__ module)插入到__main__ module中
            PyDict_SetItemString(d, "__builtins__", bimod) != 0)
            Py_FatalError("can't add __builtins__ to __main__");
        Py_DECREF(bimod);
    }
}

__main__ module是什么尊剔?在PyImport_AddModule時(shí),創(chuàng)建了一個(gè)名為namemodule后菱皆,會(huì)在module對(duì)應(yīng)的PyDictObject對(duì)象(mp_dict)設(shè)置一個(gè)名為__name__的項(xiàng)须误。__main__ module的這一項(xiàng)就是"__main__",作為主程序運(yùn)行的Python源文件就可以被視為名為__main__module仇轻。

當(dāng)Pythonpython abc.py運(yùn)行時(shí)京痢,Python在沿著名字空間尋找__name__時(shí),就會(huì)最終在__main__ module中發(fā)現(xiàn)__name__"__main__"篷店;而如果一個(gè)py文件是以import的方式加載的祭椰,則__name__不會(huì)為"__main__"

設(shè)置site-specific的module的搜索路徑

Python的第三方庫(kù)通常都是由module提供疲陕,一般來說方淤,一些規(guī)模較大的第三方庫(kù)將放在%PythonHome%/lib/site-packages目錄下,但是之前在初始化搜索路徑集合的時(shí)候并沒有將site-packages包含在內(nèi)蹄殃。

接下來Python通過initsite()函數(shù)將site-packages加入到搜索路徑中携茂。

// pythonrun.c
static void
initsite(void)
{
    PyObject *m, *f;
    // 獲得interp->modules中的site module 
    m = PyImport_ImportModule("site");
    if (m == NULL) {
        f = PySys_GetObject("stderr");
        if (Py_VerboseFlag) {
            PyFile_WriteString(
                "'import site' failed; traceback:\n", f);
            PyErr_Print();
        }
        else {
            PyFile_WriteString(
              "'import site' failed; use -v for traceback\n", f);
            PyErr_Clear();
        }
    }
    else {
        Py_DECREF(m);
    }
}

PyImport_ImportModule函數(shù)時(shí)Pythonimport機(jī)制的核心,調(diào)用這個(gè)函數(shù)相當(dāng)于Python中的import xxx窃爷,在這里進(jìn)入site.py邑蒋,其中會(huì)進(jìn)行兩個(gè)動(dòng)作:

  • site-packages路徑加入到sys.path中,對(duì)于不同平臺(tái)有不同操作
    • win32平臺(tái):%PythonHome%/lib/site-packages
      +Unix/Linux平臺(tái):
      • %sys.prefix%/lib/python<version>/site-packages(其中%sys.prefix%Pythonsys.predix
      • %sys.prefix%/lib/site-python
      • %sys.exec_prefix%/lib/python<version>/site-packages
      • %sys.exec_prefix%/lib/site-python
  • 處理site-packages目錄下的所有.pth文件中的所有路徑加入到sys.path

至此按厘,Python中絕大部分重要的初始化動(dòng)作都已經(jīng)完成了医吊,下圖是完成初始化后所有可以利用的資源:

完成初始化后的Python環(huán)境

0x03 激活Python虛擬機(jī)

上面部分算是完成了Python執(zhí)行程序所必須的基礎(chǔ)設(shè)施建設(shè),但是初始化動(dòng)作還沒有真正完成逮京,當(dāng)Python真正進(jìn)入到之前講的字節(jié)碼虛擬機(jī)后卿堂,初始化階段才算真正完成。

PythonPy_Initialize成功完成后,最終將調(diào)用PyRun_AnyFileExFlags(fp, filename == NULL ? "<stdin>" : filename, filename != NULL, &cf)草描。如果以腳本方式運(yùn)行Python览绿,則filename是文件名;如果以交互方式運(yùn)行Python穗慕,則filename會(huì)傳入"<stdini>"饿敲。第一個(gè)參數(shù)fp指向打開的腳本或者是系統(tǒng)的標(biāo)準(zhǔn)輸入流stdin

// pythonrun.c
/* Parse input from a file and execute it */
int
PyRun_AnyFileExFlags(FILE *fp, const char *filename, int closeit,
             PyCompilerFlags *flags)
{
    if (filename == NULL)
        filename = "???";
    // 根據(jù)fp是否代表交互環(huán)境逛绵,對(duì)程序流程進(jìn)行分流
    if (Py_FdIsInteractive(fp, filename)) {
        int err = PyRun_InteractiveLoopFlags(fp, filename, flags);
        if (closeit)
            fclose(fp);
        return err;
    }
    else
        return PyRun_SimpleFileExFlags(fp, filename, closeit, flags);
}

通過Py_FdIsInteractive函數(shù)判斷fp是否指向標(biāo)準(zhǔn)輸入流怀各。如果是,則進(jìn)入PyRun_InteractiveLoopFlags术浪,否則進(jìn)入PyRun_SimpleFileExFlags瓢对。

交互式運(yùn)行方式

// pythonrun.c
int
PyRun_InteractiveLoopFlags(FILE *fp, const char *filename, PyCompilerFlags *flags)
{
    PyObject *v;
    int ret;
    PyCompilerFlags local_flags;

    if (flags == NULL) {
        flags = &local_flags;
        local_flags.cf_flags = 0;
    }
    // 創(chuàng)建交互式環(huán)境提示符“>>>”
    v = PySys_GetObject("ps1");
    if (v == NULL) {
        PySys_SetObject("ps1", v = PyString_FromString(">>> "));
        Py_XDECREF(v);
    }
    // 創(chuàng)建交互式環(huán)境提示符“...”
    v = PySys_GetObject("ps2");
    if (v == NULL) {
        PySys_SetObject("ps2", v = PyString_FromString("... "));
        Py_XDECREF(v);
    }
    // 進(jìn)入一個(gè)死循環(huán),即交互式環(huán)境
    for (;;) {
        ret = PyRun_InteractiveOneFlags(fp, filename, flags);
        PRINT_TOTAL_REFS();
        if (ret == E_EOF)
            return 0;
        /*
        if (ret == E_NOMEM)
            return -1;
        */
    }
}

int
PyRun_InteractiveOneFlags(FILE *fp, const char *filename, PyCompilerFlags *flags)
{
    PyObject *m, *d, *v, *w;
    mod_ty mod;
    PyArena *arena;
    char *ps1 = "", *ps2 = "";
    int errcode = 0;

    v = PySys_GetObject("ps1");
    if (v != NULL) {
        v = PyObject_Str(v);
        if (v == NULL)
            PyErr_Clear();
        else if (PyString_Check(v))
            ps1 = PyString_AsString(v);
    }
    w = PySys_GetObject("ps2");
    if (w != NULL) {
        w = PyObject_Str(w);
        if (w == NULL)
            PyErr_Clear();
        else if (PyString_Check(w))
            ps2 = PyString_AsString(w);
    }
    // 編譯用戶在交互式環(huán)境下輸入的Python語句
    arena = PyArena_New();
    if (arena == NULL) {
        Py_XDECREF(v);
        Py_XDECREF(w);
        return -1;
    }
    mod = PyParser_ASTFromFile(fp, filename,
                   Py_single_input, ps1, ps2,
                   flags, &errcode, arena);
    Py_XDECREF(v);
    Py_XDECREF(w);
    if (mod == NULL) {
        PyArena_Free(arena);
        if (errcode == E_EOF) {
            PyErr_Clear();
            return E_EOF;
        }
        PyErr_Print();
        return -1;
    }
    // 獲得<module __main__>中維護(hù)的dict
    m = PyImport_AddModule("__main__");
    if (m == NULL) {
        PyArena_Free(arena);
        return -1;
    }
    d = PyModule_GetDict(m);
    // 執(zhí)行用戶輸入的Python語句
    v = run_mod(mod, filename, d, d, flags, arena);
    PyArena_Free(arena);
    if (v == NULL) {
        PyErr_Print();
        return -1;
    }
    Py_DECREF(v);
    if (Py_FlushLine())
        PyErr_Clear();
    return 0;
}

調(diào)用PyParser_ASTFromFile函數(shù)胰苏,對(duì)用戶在交互式環(huán)境下輸入的Python語句進(jìn)行編譯硕蛹,其結(jié)果是構(gòu)造與Python語句對(duì)應(yīng)的抽象語法樹(AST)。

然后調(diào)用run_mode硕并,將最終完成對(duì)用戶輸入的語句的執(zhí)行動(dòng)作法焰。需要注意的是:在進(jìn)入run_mode之前,會(huì)將__main__ module中維護(hù)的PyDictObject對(duì)象取出鲤孵,傳遞給run_mode壶栋,這個(gè)參數(shù)很重要,它將作為Python虛擬機(jī)開始執(zhí)行時(shí)當(dāng)前活動(dòng)的frame對(duì)象的local名字空間和global名字空間普监。

腳本文件運(yùn)行方式

// python.h
#define Py_file_input 257

// pythonrun.c
int
PyRun_SimpleFileExFlags(FILE *fp, const char *filename, int closeit,
            PyCompilerFlags *flags)
{
    PyObject *m, *d, *v;
    const char *ext;
    // 在__main__module中設(shè)置“__file__”屬性
    m = PyImport_AddModule("__main__");
    if (m == NULL)
        return -1;
    d = PyModule_GetDict(m);
    if (PyDict_GetItemString(d, "__file__") == NULL) {
        PyObject *f = PyString_FromString(filename);
        if (f == NULL)
            return -1;
        if (PyDict_SetItemString(d, "__file__", f) < 0) {
            Py_DECREF(f);
            return -1;
        }
        Py_DECREF(f);
    }
    ext = filename + strlen(filename) - 4;
    // 首先嘗試去執(zhí)行pyc文件
    if (maybe_pyc_file(fp, filename, ext, closeit)) {
        /* Try to run a pyc file. First, re-open in binary */
        if (closeit)
            fclose(fp);
        if ((fp = fopen(filename, "rb")) == NULL) {
            fprintf(stderr, "python: Can't reopen .pyc file\n");
            return -1;
        }
        /* Turn on optimization if a .pyo file is given */
        if (strcmp(ext, ".pyo") == 0)
            Py_OptimizeFlag = 1;
        v = run_pyc_file(fp, filename, d, d, flags);
    } else {
        // 執(zhí)行py腳本文件
        v = PyRun_FileExFlags(fp, filename, Py_file_input, d, d,
                      closeit, flags);
    }
        ......
    return 0;
}

PyObject *
PyRun_FileExFlags(FILE *fp, const char *filename, int start, PyObject *globals,
          PyObject *locals, int closeit, PyCompilerFlags *flags)
{
    PyObject *ret;
    mod_ty mod;
    PyArena *arena = PyArena_New();
    if (arena == NULL)
        return NULL;
    // 編譯
    mod = PyParser_ASTFromFile(fp, filename, start, 0, 0,
                   flags, NULL, arena);
    if (closeit)
        fclose(fp);
    if (mod == NULL) {
        PyArena_Free(arena);
        return NULL;
    }
    // 執(zhí)行
    ret = run_mod(mod, filename, globals, locals, flags, arena);
    PyArena_Free(arena);
    return ret;
}

同交互式執(zhí)行方式一樣贵试,腳本文件的執(zhí)行流程最后也進(jìn)入了run_mode,也同樣將__main__ module中維護(hù)的PyDictObject對(duì)象作為localglobal名字空間傳入run_mode中凯正。

啟動(dòng)虛擬機(jī)

run_mode開始毙玻,Python現(xiàn)在只剩下最后一件需要完成的工作了,那就是啟動(dòng)字節(jié)碼虛擬機(jī)廊散。

// pythonrun.c
static PyObject *
run_mod(mod_ty mod, const char *filename, PyObject *globals, PyObject *locals,
     PyCompilerFlags *flags, PyArena *arena)
{
    PyCodeObject *co;
    PyObject *v;
    // 基于AST編譯字節(jié)碼指令序列桑滩,創(chuàng)建PyCodeObject對(duì)象
    co = PyAST_Compile(mod, filename, flags, arena);
    if (co == NULL)
        return NULL;
    // 創(chuàng)建PyFrameObject對(duì)象,執(zhí)行PyCodeObject對(duì)象中的字節(jié)碼指令序列
    v = PyEval_EvalCode(co, globals, locals);
    Py_DECREF(co);
    return v;
}

首先是根據(jù)AST得到PyCodeObject對(duì)象允睹,然后通過PyEval_EvalCode函數(shù)開始喚醒字節(jié)碼虛擬機(jī)运准。

// ceval.c
PyObject *
PyEval_EvalCode(PyCodeObject *co, PyObject *globals, PyObject *locals)
{
    /* XXX raise SystemError if globals is NULL */
    return PyEval_EvalCodeEx(co,
              globals, locals,
              (PyObject **)NULL, 0,
              (PyObject **)NULL, 0,
              (PyObject **)NULL, 0,
              NULL);
}

PyObject *
PyEval_EvalCodeEx(PyCodeObject *co, PyObject *globals, PyObject *locals,
       PyObject **args, int argcount, PyObject **kws, int kwcount,
       PyObject **defs, int defcount, PyObject *closure)
{
    register PyFrameObject *f;
    register PyObject *retval = NULL;
    register PyObject **fastlocals, **freevars;
    PyThreadState *tstate = PyThreadState_GET();
    PyObject *x, *u;
    ......
    f = PyFrame_New(tstate, co, globals, locals);
    ......
    fastlocals = f->f_localsplus;
    freevars = f->f_localsplus + co->co_nlocals;
    ......
    // 真正的字節(jié)碼虛擬機(jī)(偽CPU)
    retval = PyEval_EvalFrameEx(f,0);
    return retval;
}

從操作系統(tǒng)為Python創(chuàng)建進(jìn)程開始,到Python虛擬機(jī)被喚醒缭受,再到執(zhí)行引擎循環(huán)執(zhí)行字節(jié)碼胁澳,這個(gè)過程已經(jīng)很清晰了。

名字空間

在創(chuàng)建PyFrameObject對(duì)象時(shí)米者,設(shè)置的3個(gè)名字空間:local韭畸、global宇智、builtin

  • builtin名字空間就是初始化時(shí)創(chuàng)建的__builtin__ module胰丁,Python所有線程都共享同樣的builtin名字空間(節(jié)省空間随橘,加快速度)
  • global名字空間被設(shè)置為__main__ moduledict
  • local名字空間和global名字空間一樣

歡迎關(guān)注微信公眾號(hào)(coder0x00)或掃描下方二維碼關(guān)注,我們將持續(xù)搜尋程序員必備基礎(chǔ)技能包提供給大家锦庸。


最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末机蔗,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子酸员,更是在濱河造成了極大的恐慌蜒车,老刑警劉巖讳嘱,帶你破解...
    沈念sama閱讀 218,755評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件幔嗦,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡沥潭,警方通過查閱死者的電腦和手機(jī)邀泉,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來钝鸽,“玉大人汇恤,你說我怎么就攤上這事“吻。” “怎么了因谎?”我有些...
    開封第一講書人閱讀 165,138評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)颜懊。 經(jīng)常有香客問我财岔,道長(zhǎng),這世上最難降的妖魔是什么河爹? 我笑而不...
    開封第一講書人閱讀 58,791評(píng)論 1 295
  • 正文 為了忘掉前任匠璧,我火速辦了婚禮,結(jié)果婚禮上咸这,老公的妹妹穿的比我還像新娘夷恍。我一直安慰自己,他們只是感情好媳维,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,794評(píng)論 6 392
  • 文/花漫 我一把揭開白布酿雪。 她就那樣靜靜地躺著,像睡著了一般侄刽。 火紅的嫁衣襯著肌膚如雪指黎。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,631評(píng)論 1 305
  • 那天唠梨,我揣著相機(jī)與錄音袋励,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛茬故,可吹牛的內(nèi)容都是我干的盖灸。 我是一名探鬼主播,決...
    沈念sama閱讀 40,362評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼磺芭,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼赁炎!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起钾腺,我...
    開封第一講書人閱讀 39,264評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤徙垫,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后放棒,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體姻报,經(jīng)...
    沈念sama閱讀 45,724評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評(píng)論 3 336
  • 正文 我和宋清朗相戀三年间螟,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了吴旋。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,040評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡厢破,死狀恐怖荣瑟,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情摩泪,我是刑警寧澤笆焰,帶...
    沈念sama閱讀 35,742評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站见坑,受9級(jí)特大地震影響嚷掠,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜鳄梅,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,364評(píng)論 3 330
  • 文/蒙蒙 一叠国、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧戴尸,春花似錦粟焊、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,944評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至挎峦,卻和暖如春香追,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背坦胶。 一陣腳步聲響...
    開封第一講書人閱讀 33,060評(píng)論 1 270
  • 我被黑心中介騙來泰國(guó)打工透典, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留晴楔,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,247評(píng)論 3 371
  • 正文 我出身青樓峭咒,卻偏偏與公主長(zhǎng)得像税弃,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子凑队,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,979評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容