Python虚拟机的初始化概览

简介:
今天想跟下Python虚拟机的启动,看看以调试模式跑起python_d.exe是怎么一个过程。

1. d:\Python-2.7.2\Modules\python.c文件是main函数,直接调用Py_Main函数;
2. 在Py_Main函数中,初始化函数为Py_Initialize();,而后者直接调用Py_InitializeEx(1);函数;
3. 在Py_InitializeEx函数中,首先判断是否已经初始化过,如果有则返回,没有就改下标志,开始初始化;第一步也是十分关键的一步,是调用函数(interp = PyInterpreterState_New();)创建PyInterpreterState对象(即解释器进程,现在Python一个解释器只有一个进程,所以存在一个缺点,在多核的机子上也只能存在一个进程)。
4. 在PyInterpreterState_New()函数中,首先为PyInterpreterState对象分配内存:
    PyInterpreterState *interp = (PyInterpreterState *)
                                 malloc(sizeof(PyInterpreterState));

如果分配内存成功,执行HEAD_INIT();宏:
#ifdef WITH_THREAD
#include "pythread.h"
static PyThread_type_lock head_mutex = NULL; /* Protects interp->tstate_head */
#define HEAD_INIT() (void)(head_mutex || (head_mutex = PyThread_allocate_lock()))
#define HEAD_LOCK() PyThread_acquire_lock(head_mutex, WAIT_LOCK)
#define HEAD_UNLOCK() PyThread_release_lock(head_mutex)

不论是从名称还是注释都可以看出head_mutex是用来保护解释器进程的tstate_head成员的。
在head_mutex为NULL的情况下会调用PyThread_allocate_lock()函数初始化head_mutex变量。
接着初始化其它成员。
于是,解释器进程就这么创建了……

接着立马创建线程:tstate = PyThreadState_New(interp);,继而调用new_threadstate(interp, 1);
同样地,先为线程对象分配空间:PyThreadState *tstate = (PyThreadState *)malloc(sizeof(PyThreadState));
接着一样是对线程对象进行初始化,然后切换一下线程:(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");

    if (!_PyLong_Init())
        Py_FatalError("Py_Initialize: can't init longs");

    if (!PyByteArray_Init())
        Py_FatalError("Py_Initialize: can't init bytearray");

    _PyFloat_Init();

第一个函数其实就是初始化变量static PyObject *builtin_object;为字符串“__builtins__”;
第二个函数是初始化小整数的缓存链表,这里的小整数范围是可以自定义再重新编译进行设置的,过程挺有趣的;
第三个函数初始化Long类型信息,第四个函数没做什么;
接着初始化Float类型信息。

然后是初始化interp的modules和modules_reloading成员,都是简单地调用PyDict_New()函数赋值。
如果需要的话,还会初始化Unicode编码:_PyUnicode_Init();

接着是模块初始化,代码有省略:
bimod = _PyBuiltin_Init();
interp->builtins = PyModule_GetDict(bimod);
sysmod = _PySys_Init();
interp->sysdict = PyModule_GetDict(sysmod);

还有模块导入机制、异常、警告的初始化,代码有省略:
_PyImport_Init();
_PyExc_Init();
_PyWarnings_Init();

    initmain(); /* Module __main__ */

初始化全局锁:
    /* auto-thread-state API, if available */
#ifdef WITH_THREAD
    _PyGILState_Init(interp, tstate);
#endif /* WITH_THREAD */

最后是检查stdin,stdout,stderr和设置相关信息。

然后回到Py_Main,输出版本信息以及“>>>”,等用户输入。

假设输入“a = 1”,然后按Enter键:
Python会先对用户输入进行编译(co = PyAST_Compile(mod, filename, flags, arena);),生成PyCodeObject,然后再执行:v = PyEval_EvalCode(co, globals, locals);
PyObject *
PyEval_EvalCode(PyCodeObject *co, PyObject *globals, PyObject *locals)
{
    return PyEval_EvalCodeEx(co,
                      globals, locals,
                      (PyObject **)NULL, 0,
                      (PyObject **)NULL, 0,
                      (PyObject **)NULL, 0,
                      NULL);
}

于是我们最终进入到PyEval_EvalFrameEx函数,在这里用大量的switch/case来执行指令。


目录
相关文章
|
6月前
|
存储 数据采集 大数据
Python推导式进阶指南:优雅初始化序列的科学与艺术
本文系统讲解Python推导式的用法与技巧,涵盖列表、字典、集合推导式及生成器表达式。通过代码示例和性能对比,展示推导式在数据结构初始化中的优势:简洁高效、执行速度快30%-50%。文章分析基础语法、核心应用场景(如序列构造、键值对转换、去重运算)及嵌套使用,并探讨使用边界与最佳实践,强调可读性优先原则。最后指出,合理运用推导式能显著提升代码质量和处理效率,同时避免过度复杂化的陷阱。
199 0
|
数据采集 存储 JSON
Python网络爬虫教程概览
【6月更文挑战第21天】Python网络爬虫教程概览:安装requests和BeautifulSoup库抓取网页;使用HTTP GET请求获取HTML,解析标题;利用CSS选择器提取数据;处理异步内容可选Selenium;遵循爬虫策略,处理异常,尊重法律与网站规定。
168 1
|
存储 缓存 Java
深度解密 Python 虚拟机的执行环境:栈帧对象
深度解密 Python 虚拟机的执行环境:栈帧对象
265 13
|
Python
深入解析 Python 中的对象创建与初始化:__new__ 与 __init__ 方法
深入解析 Python 中的对象创建与初始化:__new__ 与 __init__ 方法
147 1
|
存储 API 索引
一文让你搞懂 Python 虚拟机执行字节码的奥秘
一文让你搞懂 Python 虚拟机执行字节码的奥秘
257 1
|
存储 Java 开发者
用一篇文章告诉你如何篡改 Python 虚拟机
用一篇文章告诉你如何篡改 Python 虚拟机
109 0
【Pandas+Python】初始化一个全零的Dataframe
初始化一个100*3的0矩阵,变为Dataframe类型,并为每列赋值一个属性。
266 2
|
存储 JSON 算法
python标准库概览
python标准库概览
WK
|
运维 监控 API
Python在运维领域的卓越应用与工具概览
Python以清晰的语法和丰富的库资源,在运维领域大放异彩,被广泛用于自动化运维、监控、日志管理和配置部署,显著提升效率和准确性。Ansible作为IT自动化工具,利用Python和SSH实现无缝自动化,无需安装代理,兼容多种环境。Chef以Ruby为核心,通过Python API支持插件开发。Puppet采用声明式配置管理,支持Python定制开发。SaltStack功能全面,提供Python API进行高效运维。Fabric轻量级,适用于批量远程操作。Docker SDK for Python简化容器生命周期管理。
WK
362 0
|
存储 大数据 索引
Python迭代器与生成器概览
【6月更文挑战第20天】迭代器提供不依赖索引的元素访问,支持`__next__()`和`iter()`,惰性计算节省内存,但不可回溯且无长度。生成器是特殊的迭代器,用`yield`动态生成值,更节省内存,代码简洁。创建迭代器可通过`iter()`函数,而生成器通过`yield`函数或生成器表达式实现。在处理大数据时尤为有用。
125 2

推荐镜像

更多
下一篇
oss云网关配置