Python3.5源码分析-内建模块builtins初始化
发布日期:2021-07-25 13:04:42 浏览次数:8 分类:技术文章

本文共 14164 字,大约阅读时间需要 47 分钟。

Python3源码分析

本文环境python3.5.2。参考书籍<
>python官网

Python3模块初始化与加载

Python的模块分为内建的模块,函数与用户定义的模块,首先分析Python内建模块。

Python3的系统内建模块初始化

上文介绍了Python的线程对象和解释器对象,在初始化的时候,会执行_Py_InitializeEx_Private函数,会先创建解释器对象和线程对象,然后再设置系统默认的moudle,

void_Py_InitializeEx_Private(int install_sigs, int install_importlib){    ...    interp->modules = PyDict_New();                                 // 设置解释器的modules为字典类型    ...    bimod = _PyBuiltin_Init();                                      // 初始化内建函数    ...     _PyImport_FixupBuiltin(bimod, "builtins");                      //     interp->builtins = PyModule_GetDict(bimod);    ...    /* initialize builtin exceptions */    _PyExc_Init(bimod);                                             // 添加内建报错类型    sysmod = _PySys_Init();                                         // 初始化sys模块    ...    interp->sysdict = PyModule_GetDict(sysmod);                     // 设置解释器的sysdict值    ...    _PyImport_FixupBuiltin(sysmod, "sys");                          // 绑定到sys名称下    PySys_SetPath(Py_GetPath());                                    // 设置module搜索路径    PyDict_SetItemString(interp->sysdict, "modules",                         interp->modules);                          // 设置modules    ...}

此时可以看出,首先会初始化interp->modules为一个字典,然后调用_PyBuiltin_Init初始化内建函数,

PyObject *_PyBuiltin_Init(void){    PyObject *mod, *dict, *debug;    if (PyType_Ready(&PyFilter_Type) < 0 ||         PyType_Ready(&PyMap_Type) < 0 ||        PyType_Ready(&PyZip_Type) < 0)                      // 检查类型是否初始化成功        return NULL;    mod = PyModule_Create(&builtinsmodule);                 // 创建module    if (mod == NULL)        return NULL;    dict = PyModule_GetDict(mod);                           // 创建module对应的属性字典#ifdef Py_TRACE_REFS    /* "builtins" 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);                   // 添加到module中    SETBUILTIN("Ellipsis",              Py_Ellipsis);    SETBUILTIN("NotImplemented",        Py_NotImplemented);    SETBUILTIN("False",                 Py_False);    SETBUILTIN("True",                  Py_True);    SETBUILTIN("bool",                  &PyBool_Type);    SETBUILTIN("memoryview",        &PyMemoryView_Type);    SETBUILTIN("bytearray",             &PyByteArray_Type);    SETBUILTIN("bytes",                 &PyBytes_Type);    SETBUILTIN("classmethod",           &PyClassMethod_Type);    SETBUILTIN("complex",               &PyComplex_Type);    SETBUILTIN("dict",                  &PyDict_Type);    SETBUILTIN("enumerate",             &PyEnum_Type);    SETBUILTIN("filter",                &PyFilter_Type);    SETBUILTIN("float",                 &PyFloat_Type);    SETBUILTIN("frozenset",             &PyFrozenSet_Type);    SETBUILTIN("property",              &PyProperty_Type);    SETBUILTIN("int",                   &PyLong_Type);    SETBUILTIN("list",                  &PyList_Type);    SETBUILTIN("map",                   &PyMap_Type);    SETBUILTIN("object",                &PyBaseObject_Type);    SETBUILTIN("range",                 &PyRange_Type);    SETBUILTIN("reversed",              &PyReversed_Type);    SETBUILTIN("set",                   &PySet_Type);    SETBUILTIN("slice",                 &PySlice_Type);    SETBUILTIN("staticmethod",          &PyStaticMethod_Type);    SETBUILTIN("str",                   &PyUnicode_Type);    SETBUILTIN("super",                 &PySuper_Type);    SETBUILTIN("tuple",                 &PyTuple_Type);    SETBUILTIN("type",                  &PyType_Type);    SETBUILTIN("zip",                   &PyZip_Type);    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}

由该函数可以看出,Python的内建关键字都是通过该函数建立的,常用的str等内建方法。此时查看PyModule_Create函数和builtinsmodule定义,

typedef struct PyModuleDef{    PyModuleDef_Base m_base;    const char* m_name;    const char* m_doc;    Py_ssize_t m_size;    PyMethodDef *m_methods;    struct PyModuleDef_Slot* m_slots;    traverseproc m_traverse;    inquiry m_clear;    freefunc m_free;  }PyModuleDef;  ...  static struct PyModuleDef builtinsmodule = {        PyModuleDef_HEAD_INIT,        "builtins",        builtin_doc,        -1, /* multiple "initialization" just copies the module dict. */        builtin_methods,        NULL,        NULL,        NULL,        NULL    };

此时,可以看出builtinsmodule类型上文所示,定义的相关方法就是builtin_methods, PyModuleDef分别存了模块名称,模块的说明文档,文档的大小等信息,模块中获取相关的方法就从m_methods从获取相关方法,此处builtin_methods模块相关方法,

static PyMethodDef builtin_methods[] = {    {"__build_class__", (PyCFunction)builtin___build_class__,     METH_VARARGS | METH_KEYWORDS, build_class_doc},    {"__import__",      (PyCFunction)builtin___import__, METH_VARARGS | METH_KEYWORDS, import_doc},    BUILTIN_ABS_METHODDEF    BUILTIN_ALL_METHODDEF    BUILTIN_ANY_METHODDEF    ...    {"iter",            builtin_iter,       METH_VARARGS, iter_doc},    ...    {"max",             (PyCFunction)builtin_max,        METH_VARARGS | METH_KEYWORDS, max_doc},    {"min",             (PyCFunction)builtin_min,        METH_VARARGS | METH_KEYWORDS, min_doc},    {"next",            (PyCFunction)builtin_next,       METH_VARARGS, next_doc},    ...    {"print",           (PyCFunction)builtin_print,      METH_VARARGS | METH_KEYWORDS, print_doc},    ...    {"round",           (PyCFunction)builtin_round,      METH_VARARGS | METH_KEYWORDS, round_doc},    ...    {"vars",            builtin_vars,       METH_VARARGS, vars_doc},    {NULL,              NULL},};

由此可知相关的内建函数也导入到了内建模块中,此时回过头来看PyModule_Create是怎样运行的呢?

#define PyModule_Create(module) \    PyModule_Create2(module, PYTHON_API_VERSION)

此时继续查看PyModule_Create2函数的执行流程,

PyObject *PyModule_Create2(struct PyModuleDef* module, int module_api_version){    const char* name;    PyModuleObject *m;    PyInterpreterState *interp = PyThreadState_Get()->interp;                   // 获取当前的解释器    if (interp->modules == NULL)                                                // 判断当前模块是否为空        Py_FatalError("Python import machinery not initialized");    if (!PyModuleDef_Init(module))                                              // 检查PyModuleDef_Type是否初始化如果没有则初始化        return NULL;    name = module->m_name;                                                      // 获取模块名称                          ...    if ((m = (PyModuleObject*)PyModule_New(name)) == NULL)                          // 新建module对象        return NULL;    if (module->m_size > 0) {                                                       // 检查是否大于0 大于0则分配相关内存        m->md_state = PyMem_MALLOC(module->m_size);        if (!m->md_state) {            PyErr_NoMemory();            Py_DECREF(m);            return NULL;        }        memset(m->md_state, 0, module->m_size);    }    if (module->m_methods != NULL) {                                                // 检查模块包含的方法是否为空        if (PyModule_AddFunctions((PyObject *) m, module->m_methods) != 0) {            Py_DECREF(m);            return NULL;        }    }     if (module->m_doc != NULL) {                                                    // 检查参数是否为空        if (PyModule_SetDocString((PyObject *) m, module->m_doc) != 0) {            Py_DECREF(m);            return NULL;        }    }    m->md_def = module;                                                             // 保存对应的module到md_def字段    return (PyObject*)m;                                                            // 返回模块}

其中比较重要得就是PyModule_New函数,

typedef struct {    PyObject_HEAD    PyObject *md_dict;                                                       // 存储相关方法的字典    struct PyModuleDef *md_def;                                              // 对应的原模块    void *md_state;                                                 PyObject *md_weaklist;      PyObject *md_name;  /* for logging purposes after md_dict is cleared */  // 模块名称} PyModuleObject;...PyObject *PyModule_NewObject(PyObject *name){    PyModuleObject *m;    m = PyObject_GC_New(PyModuleObject, &PyModule_Type);                    // 申请内存    if (m == NULL)        return NULL;    m->md_def = NULL;    m->md_state = NULL;    m->md_weaklist = NULL;    m->md_name = NULL;    m->md_dict = PyDict_New();                                              // 设置属性字典    if (module_init_dict(m, m->md_dict, name, NULL) != 0)        goto fail;    PyObject_GC_Track(m);    return (PyObject *)m;                                                   // 返回 fail:    Py_DECREF(m);    return NULL;}PyObject *PyModule_New(const char *name){    PyObject *nameobj, *module;    nameobj = PyUnicode_FromString(name);                                   // 名称转换    if (nameobj == NULL)        return NULL;    module = PyModule_NewObject(nameobj);                                   // 初始化PyModuleObject对象    Py_DECREF(nameobj);    return module;}

由此可知生成的module是一个PyModuleObject类型,此时返回_PyBuiltin_Init函数中继续执行

dict = PyModule_GetDict(mod);

此时就将mod对应的为空的属性字典返回,然后就向dict添加相关字典对应的方法,

SETBUILTIN("None",                  Py_None);

此时就相关内建方法设置到dict中,此时相对应的类型就设置到了module对应的字典中,此时初始化完成后返回_Py_InitializeEx_Private函数继续执行,接着就执行到;

_PyImport_FixupBuiltin(bimod, "builtins");

该函数对应的代码如下,

int_PyImport_FixupBuiltin(PyObject *mod, const char *name){    int res;    PyObject *nameobj;    nameobj = PyUnicode_InternFromString(name);                     // 名称转换    if (nameobj == NULL)        return -1;    res = _PyImport_FixupExtensionObject(mod, nameobj, nameobj);    // 导入到扩展的extension中    Py_DECREF(nameobj);    return res;}

调用了_PyImport_FixupExtensionObject函数将传入的mod导入到extension中,

/* See _PyImport_FixupExtensionObject() below */static PyObject *extensions = NULL;/* Magic for extension modules (built-in as well as dynamically   loaded).  To prevent initializing an extension module more than   once, we keep a static dictionary 'extensions' keyed by the tuple   (module name, module name)  (for built-in modules) or by   (filename, module name) (for dynamically loaded modules), containing these   modules.  A copy of the module's dictionary is stored by calling   _PyImport_FixupExtensionObject() immediately after the module initialization   function succeeds.  A copy can be retrieved from there by calling   _PyImport_FindExtensionObject().   Modules which do support multiple initialization set their m_size   field to a non-negative number (indicating the size of the   module-specific state). They are still recorded in the extensions   dictionary, to avoid loading shared libraries twice.*/              // 导入的module作为一份备份,避免共享库时导入两次int_PyImport_FixupExtensionObject(PyObject *mod, PyObject *name,                               PyObject *filename){    PyObject *modules, *dict, *key;    struct PyModuleDef *def;    int res;    if (extensions == NULL) {                               // 检查静态extensions是否为空        extensions = PyDict_New();                          // 为空初始化一个字典类型        if (extensions == NULL)                             // 初始化值为空则返回错误值            return -1;    }    if (mod == NULL || !PyModule_Check(mod)) {              // 检查传入的mod是否为空        PyErr_BadInternalCall();        return -1;    }    def = PyModule_GetDef(mod);                             // 获取mod中定义的方法    if (!def) {        PyErr_BadInternalCall();        return -1;    }    modules = PyImport_GetModuleDict();                     // 获取当前解释器的modules数据    if (PyDict_SetItem(modules, name, mod) < 0)             // 设置对应的name和mod到modules字典中        return -1;    if (_PyState_AddModule(mod, def) < 0) {        PyDict_DelItem(modules, name);        return -1;    }    if (def->m_size == -1) {                                // builtins初始时为-1        if (def->m_base.m_copy) {            /* Somebody already imported the module,               likely under a different name.               XXX this should really not happen. */            Py_CLEAR(def->m_base.m_copy);        }        dict = PyModule_GetDict(mod);                       // 获取mod的属性字典        if (dict == NULL)            return -1;        def->m_base.m_copy = PyDict_Copy(dict);             // 复制一份,设置到def中的m_copy中        if (def->m_base.m_copy == NULL)            return -1;    }    key = PyTuple_Pack(2, filename, name);                  // 生成一个tuple    if (key == NULL)        return -1;    res = PyDict_SetItem(extensions, key, (PyObject *)def);  // 设置到extentsions中    Py_DECREF(key);    if (res < 0)        return -1;    return 0;}

其中, extentsions作为全局静态变量存在,保存全局导入的模块,可以实现已经导入的模块避免二次导入实现,此刻返回_Py_InitializeEx_Private函数继续执行,

interp->builtins = PyModule_GetDict(bimod);.../* initialize builtin exceptions */_PyExc_Init(bimod);

获取bimod属性的字典值,该值就是_PyBuiltin_Init初始化时,填入的dict该d字典包括None,False, True等字典值,将该字典复制到解释器对象的builtins中,然后初始化内建的错误类型,查看_PyExc_Init函数,

void_PyExc_Init(PyObject *bltinmod){    PyObject *bdict;    PRE_INIT(BaseException)                 // 检查该类型是否初始化    PRE_INIT(Exception)    ...    bdict = PyModule_GetDict(bltinmod);     // 获取传入的模块的属性字典    if (bdict == NULL)        Py_FatalError("exceptions bootstrapping error.");    POST_INIT(BaseException)                // 将BaseException设置到bdict中    POST_INIT(Exception)    ...}

查看PRE_INIT和POST_INIT宏,

#define PRE_INIT(TYPE) \if (!(_PyExc_ ## TYPE.tp_flags & Py_TPFLAGS_READY)) { \    if (PyType_Ready(&_PyExc_ ## TYPE) < 0) \        Py_FatalError("exceptions bootstrapping error."); \    Py_INCREF(PyExc_ ## TYPE); \}#define POST_INIT(TYPE) \    if (PyDict_SetItemString(bdict, # TYPE, PyExc_ ## TYPE)) \        Py_FatalError("Module dictionary insertion problem.");

由宏展开可知,先检查类型是否已经初始化,然后将对应的类型添加到bdict字典中,至此就将内建的类型初始化完成。

总结

根据Python的初始化流程,此时初始化了Python的内建builtins模块的初始化模型,可用如下图所示描述初始化过程,

builtins初始化后内存布局

主要初始化了Python的内部定义的类型None,False,和基础的异常类型等方法。

转载地址:https://blog.csdn.net/qq_33339479/article/details/81501802 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:Python3.5源码分析-sys模块及site模块导入
下一篇:python3.5源码分析-启动与虚拟机

发表评论

最新留言

逛到本站,mark一下
[***.202.152.39]2024年03月30日 13时31分26秒