Python3源码分析

本文环境python3.5.2。
参考书籍<<Python源码剖析>>
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);                 // 创建moduleif (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_METHODDEFBUILTIN_ALL_METHODDEFBUILTIN_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_HEADPyObject *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 dynamicallyloaded).  To prevent initializing an extension module more thanonce, 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 thesemodules.  A copy of the module's dictionary is stored by calling_PyImport_FixupExtensionObject() immediately after the module initializationfunction succeeds.  A copy can be retrieved from there by calling_PyImport_FindExtensionObject().Modules which do support multiple initialization set their m_sizefield to a non-negative number (indicating the size of themodule-specific state). They are still recorded in the extensionsdictionary, 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初始时为-1if (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);                  // 生成一个tupleif (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模块的初始化模型,可用如下图所示描述初始化过程,

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

Python3.5源码分析-内建模块builtins初始化相关推荐

  1. FreeCAD源码分析:FreeCADGui模块

    FreeCAD源码分析:FreeCADGui模块 济南友泉软件有限公司 FreeCADGui项目实现了界面操作.模型显示与交互等相关功能,项目构建生成FreeCAD(_d).dll动态链接库. Fre ...

  2. elasticsearch源码分析之search模块(server端)

    elasticsearch源码分析之search模块(server端) 继续接着上一篇的来说啊,当client端将search的请求发送到某一个node之后,剩下的事情就是server端来处理了,具体 ...

  3. elasticsearch源码分析之search模块(client端)

    elasticsearch源码分析之search模块(client端) 注意,我这里所说的都是通过rest api来做的搜索,所以对于接收到请求的节点,我姑且将之称之为client端,其主要的功能我们 ...

  4. MyBatis 源码分析 - 内置数据源

    1.简介 本篇文章将向大家介绍 MyBatis 内置数据源的实现逻辑.搞懂这些数据源的实现,可使大家对数据源有更深入的认识.同时在配置这些数据源时,也会更清楚每种属性的意义和用途.因此,如果大家想知其 ...

  5. Python3.5源码分析-sys模块及site模块导入

    Python3源码分析 本文环境python3.5.2. 参考书籍<<Python源码剖析>> python官网 Python3的sys模块初始化 根据分析完成builtins ...

  6. python3.5源码分析-启动与虚拟机

    Python3源码分析 本文环境python3.5.2. 参考书籍<<Python源码剖析>> python官网 Python3启动流程概述 本文基于python3分析其基本的 ...

  7. Python3.5源码分析-List概述

    Python3源码分析 本文环境python3.5.2. 参考书籍<<Python源码剖析>> python官网 Python3的List对象 list对象是一个变长对象,在运 ...

  8. Python3.5源码分析-内存管理

    Python3源码分析 本文环境python3.5.2. 参考书籍<<Python源码剖析>> python官网 Python3的内存管理概述 python提供了对内存的垃圾收 ...

  9. Python源码学习:内建类型简析并简析int对象

    Python源码分析 本文环境python2.5系列 参考书籍<<Python源码剖析>> 上一篇文章中已经大致分析了下,Python的启动执行流程,现在我们分析一下Pytho ...

最新文章

  1. 这所211高校通知不放寒假!校园将实行封闭管理!
  2. 独家 | 不同机器学习模型的决策边界(附代码)
  3. 7 虚拟磁盘恢复虚拟机
  4. 洛谷【算法1-4】递推与递归
  5. NYOJ_5743Distribution(第八届河南省程序设计大赛)
  6. wxWidgets:wxStdOutputStreamBuffer类用法
  7. sysdig案例分析 - 哪些文件正在被进程访问
  8. 第三十九期:收藏 | 第一次有人把“分布式事务”讲的这么简单明了
  9. python 3.7下载安装scrapy_win10上python3.7安装scrapy1.5.1
  10. pycharm的使用技巧
  11. 微波遥感SNAP(二)——基于Sentinel-1雷达数据反演矿区地表形变
  12. JAVA最全最细基础知识点
  13. Android混淆文件配置
  14. 教务管理系统:成绩、课表查询接口设计及抢课、监控功能实现
  15. 图形的装饰教案计算机,《有趣的图形》中班教案
  16. 为什么大家都说SELECT * 效率低
  17. 基于改进注意力机制的U-Net模型实现及应用(keras框架实现)
  18. 07-HTML5举例:简单的视频播放器
  19. DEVOPS架构师 -- 05从零开始构建基于Kubernetes的DevOps平台
  20. Mybatis核心配置文件

热门文章

  1. 使用深度学习阅读和分类扫描文档
  2. 公路病害检测有了“智慧眼”,思谋AI“助力”广东省高速公路
  3. 自研芯片架构 ,这家中国公司发布DPU芯片计划
  4. 程序员会懂的冷笑话:各大编程语言的内心独白
  5. 深入卷积神经网络背后的数学原理 | 技术头条
  6. 算力超英伟达?华为推出两款“昇腾”芯片;五大AI战略正式公布
  7. 你有一张邀请函:全球AI技术开发日南京站——9月8日走进地平线
  8. 构建人工智能产学研生态体系,中国软件行业协会智能应用服务分会在京正式成立
  9. 推荐一款基于 SpringBoot 的接口快速开发框架
  10. 我用Java+Redis+ES+Kibana技术对数百万知乎用户进行了数据分析,得到了这些...