美文网首页
大师兄的Python源码学习笔记(三十一): 运行环境初始化(三

大师兄的Python源码学习笔记(三十一): 运行环境初始化(三

作者: superkmi | 来源:发表于2021-09-03 09:06 被阅读0次

大师兄的Python源码学习笔记(三十): 运行环境初始化(二)
大师兄的Python源码学习笔记(三十二): 运行环境初始化(四)

2. 创建sys module
2.1 sys module的备份
  • __builtin__ module之后,Python会用同样的流程设置sys module,并像设置interp->builtins一样设置interp->sysdict
Python\pylifecycle.c

static _PyInitError
new_interpreter(PyThreadState **tstate_p)
{
    PyInterpreterState *interp;
    PyThreadState *tstate, *save_tstate;
    PyObject *bimod, *sysmod;
    _PyInitError err;
   ... ...
    sysmod = _PyImport_FindBuiltin("sys", modules);
    if (sysmod != NULL) {
        interp->sysdict = PyModule_GetDict(sysmod);
        if (interp->sysdict == NULL)
            goto handle_error;
        Py_INCREF(interp->sysdict);
        PyDict_SetItemString(interp->sysdict, "modules", modules);
    ... ...
}
  • 通过_PyImport_FindBuiltin创建sys module,并通过_PyImport_FindExtensionObjectEx将其备份:
Python\import.c

PyObject *
_PyImport_FindBuiltin(const char *name, PyObject *modules)
{
    PyObject *res, *nameobj;
    nameobj = PyUnicode_InternFromString(name);
    if (nameobj == NULL)
        return NULL;
    res = _PyImport_FindExtensionObjectEx(nameobj, nameobj, modules);
    Py_DECREF(nameobj);
    return res;
}
Python\import.c

static PyObject *extensions = NULL;
... ...
PyObject *
_PyImport_FindExtensionObjectEx(PyObject *name, PyObject *filename,
                                PyObject *modules)
{
    PyObject *mod, *mdict, *key;
    PyModuleDef* def;
    if (extensions == NULL)
        return NULL;
    key = PyTuple_Pack(2, filename, name);
    if (key == NULL)
        return NULL;
    def = (PyModuleDef *)PyDict_GetItem(extensions, key);
    Py_DECREF(key);
    if (def == NULL)
        return NULL;
    if (def->m_size == -1) {
        /* Module does not support repeated initialization */
        if (def->m_base.m_copy == NULL)
            return NULL;
        mod = _PyImport_AddModuleObject(name, modules);
        if (mod == NULL)
            return NULL;
        mdict = PyModule_GetDict(mod);
        if (mdict == NULL)
            return NULL;
        if (PyDict_Update(mdict, def->m_base.m_copy))
            return NULL;
    }
    else {
        if (def->m_base.m_init == NULL)
            return NULL;
        mod = def->m_base.m_init();
        if (mod == NULL)
            return NULL;
        if (PyObject_SetItem(modules, name, mod) == -1) {
            Py_DECREF(mod);
            return NULL;
        }
        Py_DECREF(mod);
    }
    if (_PyState_AddModule(mod, def) < 0) {
        PyMapping_DelItem(modules, name);
        Py_DECREF(mod);
        return NULL;
    }
    if (Py_VerboseFlag)
        PySys_FormatStderr("import %U # previously loaded (%R)\n",
                          name, filename);
    return mod;

}
  • 从上一段代码可以看出,Python内部维护了一个全局变量extensions,它是一个PyDictObject对象,用于维护所有已经被Python加载的module中的PyDictObject的一个备份。
  • 当Python系统的module集合中的某个标准扩展module被删除后不久又被重新加载时,Python不需要再次初始化这些module,而是从extensions中备份的PyDictObject对象来创建一个新的module即可。
  • 这也说明了为什么Python中的标准扩展module是不会在运行时动态改变的。
  • 在完成了__builtin__sys两个module对象的设置之后,PyInterpreterState对象PyThreadState对象在内存中如上图所示。
  • 注意,与之前的源码相同,在上图中__builtins__sys指向的是PyDictObject对象,而不是PyModuleObject对象。
2.2 设置module的搜索路径
  • Python在创建了sys module之后,会在其中设置一个搜索module时的默认搜索路径集合
Python\sysmodule.c

void
PySys_SetPath(const wchar_t *path)
{
    PyObject *v;
    if ((v = makepathobject(path, DELIM)) == NULL)
        Py_FatalError("can't create sys.path");
    if (_PySys_SetObjectId(&PyId_path, v) != 0)
        Py_FatalError("can't assign sys.path");
    Py_DECREF(v);
}
Python\sysmodule.c

static PyObject *
makepathobject(const wchar_t *path, wchar_t delim)
{
    int i, n;
    const wchar_t *p;
    PyObject *v, *w;

    n = 1;
    p = path;
    while ((p = wcschr(p, delim)) != NULL) {
        n++;
        p++;
    }
    v = PyList_New(n);
    if (v == NULL)
        return NULL;
    for (i = 0; ; i++) {
        p = wcschr(path, delim);
        if (p == NULL)
            p = path + wcslen(path); /* End of string */
        w = PyUnicode_FromWideChar(path, (Py_ssize_t)(p - path));
        if (w == NULL) {
            Py_DECREF(v);
            return NULL;
        }
        PyList_SET_ITEM(v, i, w);
        if (*p == '\0')
            break;
        path = p+1;
    }
    return v;
}
Python\sysmodule.c

int
_PySys_SetObjectId(_Py_Identifier *key, PyObject *v)
{
    PyThreadState *tstate = PyThreadState_GET();
    PyObject *sd = tstate->interp->sysdict;
    if (v == NULL) {
        if (_PyDict_GetItemId(sd, key) == NULL)
            return 0;
        else
            return _PyDict_DelItemId(sd, key);
    }
    else
        return _PyDict_SetItemId(sd, key, v);
}
  • makepathobject中,Python会创建一个PyListObject对象,这个list中包含了一组PyStringObject对象,每一个PyStringObject对象的内容就是一个module的搜索路径。
  • 最终,这个PyListObject对象会在_PySys_SetObjectId中被插入到interp->sysdict,也就是sys module维护的PyDictObject对象中。
  • Python随后还会进行一些琐碎的动作,其中包括初始化import环境,初始化内建异常。
Python\pylifecycle.c

_PyInitError
_Py_InitializeCore_impl(PyInterpreterState **interp_p,
                        const _PyCoreConfig *core_config)
{
    PyInterpreterState *interp;
    _PyInitError err;

    ... ...
    err = _PyImport_Init(interp);
    ... ...
}
Python\pylifecycle.c

static _PyInitError
new_interpreter(PyThreadState **tstate_p)
{
    PyInterpreterState *interp;
    PyThreadState *tstate, *save_tstate;
    PyObject *bimod, *sysmod;
    _PyInitError err;

    ... ...

    bimod = _PyImport_FindBuiltin("builtins", modules);
    if (bimod != NULL) {
        interp->builtins = PyModule_GetDict(bimod);
        if (interp->builtins == NULL)
            goto handle_error;
        Py_INCREF(interp->builtins);
    }
    else if (PyErr_Occurred()) {
        goto handle_error;
    }

    /* initialize builtin exceptions */
    _PyExc_Init(bimod);

    ... ...
}

相关文章

网友评论

      本文标题:大师兄的Python源码学习笔记(三十一): 运行环境初始化(三

      本文链接:https://www.haomeiwen.com/subject/ihpniltx.html