Python3.5源码分析-内建模块builtins初始化
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初始化相关推荐
- FreeCAD源码分析:FreeCADGui模块
FreeCAD源码分析:FreeCADGui模块 济南友泉软件有限公司 FreeCADGui项目实现了界面操作.模型显示与交互等相关功能,项目构建生成FreeCAD(_d).dll动态链接库. Fre ...
- elasticsearch源码分析之search模块(server端)
elasticsearch源码分析之search模块(server端) 继续接着上一篇的来说啊,当client端将search的请求发送到某一个node之后,剩下的事情就是server端来处理了,具体 ...
- elasticsearch源码分析之search模块(client端)
elasticsearch源码分析之search模块(client端) 注意,我这里所说的都是通过rest api来做的搜索,所以对于接收到请求的节点,我姑且将之称之为client端,其主要的功能我们 ...
- MyBatis 源码分析 - 内置数据源
1.简介 本篇文章将向大家介绍 MyBatis 内置数据源的实现逻辑.搞懂这些数据源的实现,可使大家对数据源有更深入的认识.同时在配置这些数据源时,也会更清楚每种属性的意义和用途.因此,如果大家想知其 ...
- Python3.5源码分析-sys模块及site模块导入
Python3源码分析 本文环境python3.5.2. 参考书籍<<Python源码剖析>> python官网 Python3的sys模块初始化 根据分析完成builtins ...
- python3.5源码分析-启动与虚拟机
Python3源码分析 本文环境python3.5.2. 参考书籍<<Python源码剖析>> python官网 Python3启动流程概述 本文基于python3分析其基本的 ...
- Python3.5源码分析-List概述
Python3源码分析 本文环境python3.5.2. 参考书籍<<Python源码剖析>> python官网 Python3的List对象 list对象是一个变长对象,在运 ...
- Python3.5源码分析-内存管理
Python3源码分析 本文环境python3.5.2. 参考书籍<<Python源码剖析>> python官网 Python3的内存管理概述 python提供了对内存的垃圾收 ...
- Python源码学习:内建类型简析并简析int对象
Python源码分析 本文环境python2.5系列 参考书籍<<Python源码剖析>> 上一篇文章中已经大致分析了下,Python的启动执行流程,现在我们分析一下Pytho ...
最新文章
- 这所211高校通知不放寒假!校园将实行封闭管理!
- 独家 | 不同机器学习模型的决策边界(附代码)
- 7 虚拟磁盘恢复虚拟机
- 洛谷【算法1-4】递推与递归
- NYOJ_5743Distribution(第八届河南省程序设计大赛)
- wxWidgets:wxStdOutputStreamBuffer类用法
- sysdig案例分析 - 哪些文件正在被进程访问
- 第三十九期:收藏 | 第一次有人把“分布式事务”讲的这么简单明了
- python 3.7下载安装scrapy_win10上python3.7安装scrapy1.5.1
- pycharm的使用技巧
- 微波遥感SNAP(二)——基于Sentinel-1雷达数据反演矿区地表形变
- JAVA最全最细基础知识点
- Android混淆文件配置
- 教务管理系统:成绩、课表查询接口设计及抢课、监控功能实现
- 图形的装饰教案计算机,《有趣的图形》中班教案
- 为什么大家都说SELECT * 效率低
- 基于改进注意力机制的U-Net模型实现及应用(keras框架实现)
- 07-HTML5举例:简单的视频播放器
- DEVOPS架构师 -- 05从零开始构建基于Kubernetes的DevOps平台
- Mybatis核心配置文件
热门文章
- 使用深度学习阅读和分类扫描文档
- 公路病害检测有了“智慧眼”,思谋AI“助力”广东省高速公路
- 自研芯片架构 ,这家中国公司发布DPU芯片计划
- 程序员会懂的冷笑话:各大编程语言的内心独白
- 深入卷积神经网络背后的数学原理 | 技术头条
- 算力超英伟达?华为推出两款“昇腾”芯片;五大AI战略正式公布
- 你有一张邀请函:全球AI技术开发日南京站——9月8日走进地平线
- 构建人工智能产学研生态体系,中国软件行业协会智能应用服务分会在京正式成立
- 推荐一款基于 SpringBoot 的接口快速开发框架
- 我用Java+Redis+ES+Kibana技术对数百万知乎用户进行了数据分析,得到了这些...