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来执行指令。

时间: 2025-01-29 22:25:11

Python虚拟机的初始化概览的相关文章

[笔记]Python虚拟机对函数的解释

demo.py: i = 1 def f(): j = 2 f() test.py: import dis source = open('./demo.py').read() co = compile(source, './demo.py', 'exec') print(co.co_name) dis.dis(co) print("\n") fCode = co.co_consts[1] print(fCode.co_name) dis.dis(fCode) 输出: <modul

代码-关于python类的初始化问题

问题描述 关于python类的初始化问题 代码如下: class Fruit: def init(self,*args): for arg in args: arg(self) def has_not_harvest(self): self.has_harvest = False def setColor(color): def method(self): self.color = color return method 以上是关于类Fruit的定义,接下来实例化的时候出现问题,代码如下: ap

Python中list初始化方法示例_python

本文实例讲述了Python中list初始化方法.分享给大家供大家参考,具体如下: 1.基本方法. lst = [1, 2, 3, 4, 5] 2.初始化连续数字. >>> lst = [n for n in range(5, 10)] >>> print(lst) [5, 6, 7, 8, 9] 3.初始化n个相同值.(两种方式) >>> lst = ['x' for n in range(5)] >>> print(lst) ['x

[笔记]Python虚拟机对创建基本内置对象的执行过程

同样的,有demo.py代码如下: i = 1 s = "Python" d = {"1":1, "2":2} l = [2, 3] 有test.py代码如下: import dis source = open('./demo.py').read() co = compile(source, './demo.py', 'exec') dis.dis(co) 输出如下: 1 0 LOAD_CONST 0 (1) 3 STORE_NAME 0 (i)

Python数据结构之集合概览

Python数据结构之集合概览集合(collection),正如其名称所示,是可以作为概念性的单位来处理的一组零个或多个项.几乎软件的每一个重要部分都涉及集合的使用.尽管我们在计算机科学中所学的一些内容已经随着技术的变化逐渐消失,但组织集合的基本原理并没有变化.尽管集合在结构和用法上各不相同,但是,所有的集合都有着相同的基本作用,即帮助程序员有效地在程序中组织数据. 可以从两个视角来看待集合.集合的用户和客户关注它们在各种应用程序中能做些什么.集合的开发者和实现者关注它们作为通用资源的最佳性能.

[笔记]Python虚拟机如何执行“i = 1”

首先写一个demo.py,里面只有一句: i = 1 接着写一个test.py,内容如下: import dis source = open('./demo.py').read() co = compile(source, './demo.py', 'exec') dis.dis(co) 输出: 1 0 LOAD_CONST 0 (1) 3 STORE_NAME 0 (i) 6 LOAD_CONST 1 (None) 9 RETURN_VALUE 利用Python库提供的dis工具,可以对其反汇

[笔记]Python虚拟机对if语句的解释

demo.py代码如下: a = 1 if a > 0: pass elif a == 0: pass else: pass test.py代码如下: import dis source = open('./demo.py').read() co = compile(source, './demo.py', 'exec') dis.dis(co) 输出结果如下: 1 0 LOAD_CONST 0 (1) 3 STORE_NAME 0 (a) 2 6 LOAD_NAME 0 (a) 9 LOAD_

Openstack 实现技术分解 (2) 虚拟机初始化工具 — Cloud-Init &amp;amp; metadata &amp;amp; userdata

目录 目录 前文列表 扩展阅读 系统环境 前言 Cloud-init Cloud-init 的配置文件 metadata userdata metadata 和 userdata 的区别 metadata 的服务机制 ConfigDrive Metadata RESTful 前文列表 Openstack 实现技术分解 (1) 开发环境 - Devstack 部署案例详解 扩展阅读 Documentation - Cloud-Init 0.7.9 documentation 系统环境 Devsta

Python Ubuntu虚拟机深度学习入门

更多深度文章,请关注云计算频道:https://yq.aliyun.com/cloud 当你打算开始学习深度学习+Python时,我强烈建议你使用Linux环境.因为深度学习工具可以更轻松地在Linux上进行配置和安装,从而可以快速开发和运行神经网络. 当然,配置你自己的深度学习+ Python + Linux开发环境可能是相当麻烦的任务, 特别是如果你的Linux是新手入门,使用命令行/终端,或手动编译和安装软件包时可能是非常困难的. 为了帮助你开始深度学习+ Python的学习,我已经创建了