Python3.5源码分析-sys模块及site模块导入
发布日期:2021-07-25 13:04:43 浏览次数:11 分类:技术文章

本文共 13246 字,大约阅读时间需要 44 分钟。

Python3源码分析

本文环境python3.5.2。参考书籍<
>python官网

Python3的sys模块初始化

根据分析完成builtins初始化后,继续分析sys模块的初始化,继续分析_Py_InitializeEx_Private函数的执行,

void_Py_InitializeEx_Private(int install_sigs, int install_importlib){    ...    sysmod = _PySys_Init();    if (sysmod == NULL)        Py_FatalError("Py_Initialize: can't initialize sys");    interp->sysdict = PyModule_GetDict(sysmod);    if (interp->sysdict == NULL)        Py_FatalError("Py_Initialize: can't initialize sys dict");    Py_INCREF(interp->sysdict);    _PyImport_FixupBuiltin(sysmod, "sys");    PySys_SetPath(Py_GetPath());    PyDict_SetItemString(interp->sysdict, "modules",                         interp->modules);    ...}

此时继续分析,_PySys_Init函数,

PyObject *_PySys_Init(void){    PyObject *m, *sysdict, *version_info;    int res;    m = PyModule_Create(&sysmodule);                                        // 创建模块    if (m == NULL)        return NULL;    sysdict = PyModule_GetDict(m);                                          // 获取模块的属性字典#define SET_SYS_FROM_STRING_BORROW(key, value)             \    do {                                                   \        PyObject *v = (value);                             \        if (v == NULL)                                     \            return NULL;                                   \        res = PyDict_SetItemString(sysdict, key, v);       \                // 设置到sysdict字典中        if (res < 0) {                                     \            return NULL;                                   \        }                                                  \    } while (0)#define SET_SYS_FROM_STRING(key, value)                    \    do {                                                   \        PyObject *v = (value);                             \        if (v == NULL)                                     \            return NULL;                                   \        res = PyDict_SetItemString(sysdict, key, v);       \                // 设置到sysdict字典中        Py_DECREF(v);                                      \        if (res < 0) {                                     \            return NULL;                                   \        }                                                  \    } while (0)    ...    /* stdin/stdout/stderr are set in pylifecycle.c */    SET_SYS_FROM_STRING_BORROW("__displayhook__",                               PyDict_GetItemString(sysdict, "displayhook"));    SET_SYS_FROM_STRING_BORROW("__excepthook__",                               PyDict_GetItemString(sysdict, "excepthook"));    SET_SYS_FROM_STRING("version",                         PyUnicode_FromString(Py_GetVersion()));        // 版本相关信息    ...         SET_SYS_FROM_STRING("platform",                        PyUnicode_FromString(Py_GetPlatform()));        // 平台相关信息    ...     /* initialize hash_info */    if (Hash_InfoType.tp_name == NULL) {        if (PyStructSequence_InitType2(&Hash_InfoType, &hash_info_desc) < 0)            return NULL;    }    SET_SYS_FROM_STRING("hash_info",                        get_hash_info());                               // hash相关信息    ...    SET_SYS_FROM_STRING("builtin_module_names",                        list_builtin_module_names());                   // 内建模块信息#if PY_BIG_ENDIAN    SET_SYS_FROM_STRING("byteorder",                        PyUnicode_FromString("big"));                   // 大端排序#else    SET_SYS_FROM_STRING("byteorder",                        PyUnicode_FromString("little"));                // 小断排序#endif    ..    SET_SYS_FROM_STRING_BORROW("warnoptions", warnoptions);    SET_SYS_FROM_STRING_BORROW("_xoptions", get_xoptions());    ...    SET_SYS_FROM_STRING("flags", make_flags());                         // 获取当前运行的flags    ...#ifdef WITH_THREAD    SET_SYS_FROM_STRING("thread_info", PyThread_GetInfo());             // 返回线程相关信息#endif    ...    return m;}

由该函数可知,初始了相关的函数或属性来描述和提供系统平台相关信息,完成后,

interp->sysdict = PyModule_GetDict(sysmod);    if (interp->sysdict == NULL)        Py_FatalError("Py_Initialize: can't initialize sys dict");    Py_INCREF(interp->sysdict);    _PyImport_FixupBuiltin(sysmod, "sys");    PySys_SetPath(Py_GetPath());

继续执行已经分析过的将sysmod设置到extensions中,设置interp的sysdict为初始化完成的字典,调用PySys_SetPath设置搜索路径,接下来分析一下该函数,

wchar_t *Py_GetPath(void){    if (!module_search_path)            // 如果module_search_path没有初始化        calculate_path();               // 创建搜索路径    return module_search_path;          }   voidPySys_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)     // 设置到interp->sysdict字典中        Py_FatalError("can't assign sys.path");    Py_DECREF(v);}

对于calculate_path和makepathobject函数可自行分析,这就设置好了模块的搜索路径,此后继续执行,

PyDict_SetItemString(interp->sysdict, "modules",                     interp->modules);

将interp的sysdict中添加modules,该modules就是添加的modules,至此sys模块的初始化完成。

Python3的main和site-packages的初始化

此时_Py_InitializeEx_Private执行如下代码,

void_Py_InitializeEx_Private(int install_sigs, int install_importlib){    ...    _PyImport_Init();                               // 初始化导入模块    ...    import_init(interp, sysmod);    ...    if (install_sigs)        initsigs(); /* Signal handling stuff, including initintr() */  // 注册相关信号    initmain(interp); /* Module __main__ */                            // 设置成__main__    ...    if (!Py_NoSiteFlag)        initsite(); /* Module site */                                  // 导入site中的模块}

调用到_PyImport_Init,

void_PyImport_Init(void){    PyInterpreterState *interp = PyThreadState_Get()->interp;       // 获取解释器    initstr = PyUnicode_InternFromString("__init__");               // 设置__init__    if (initstr == NULL)        Py_FatalError("Can't initialize import variables");    interp->builtins_copy = PyDict_Copy(interp->builtins);          // 拷贝解释器的builtins到builtins_copy    if (interp->builtins_copy == NULL)        Py_FatalError("Can't backup builtins dict");}

主要工作就是将interp的builtins设置到builtins_copy中,此时执行完后,执行到initsigs,

PyOS_sighandler_tPyOS_setsig(int sig, PyOS_sighandler_t handler){#ifdef HAVE_SIGACTION    /* Some code in Modules/signalmodule.c depends on sigaction() being     * used here if HAVE_SIGACTION is defined.  Fix that if this code     * changes to invalidate that assumption.     */    struct sigaction context, ocontext;    context.sa_handler = handler;    sigemptyset(&context.sa_mask);    context.sa_flags = 0;    if (sigaction(sig, &context, &ocontext) == -1)        return SIG_ERR;    return ocontext.sa_handler;#else    PyOS_sighandler_t oldhandler;    oldhandler = signal(sig, handler);          // 设置信号量#ifdef HAVE_SIGINTERRUPT    siginterrupt(sig, 1);#endif    return oldhandler;#endif}voidPyOS_InitInterrupts(void){    PyObject *m = PyImport_ImportModule("_signal");     // 导入_signal    if (m) {        Py_DECREF(m);    }}...static voidinitsigs(void){#ifdef SIGPIPE    PyOS_setsig(SIGPIPE, SIG_IGN);#endif#ifdef SIGXFZ    PyOS_setsig(SIGXFZ, SIG_IGN);#endif#ifdef SIGXFSZ    PyOS_setsig(SIGXFSZ, SIG_IGN);#endif    PyOS_InitInterrupts(); /* May imply initsignal() */             // 注册信号量    if (PyErr_Occurred()) {        Py_FatalError("Py_Initialize: can't import signal");    }}

主要执行的工作就是将相关的信号任务注册,执行完成后,执行initmain(interp)函数,

/* Create __main__ module */static voidinitmain(PyInterpreterState *interp){    PyObject *m, *d, *loader;    m = PyImport_AddModule("__main__");                                     // 添加一个__main__ module    if (m == NULL)        Py_FatalError("can't create __main__ module");    d = PyModule_GetDict(m);                                                // 获取新建模块的属性字典    if (PyDict_GetItemString(d, "__builtins__") == NULL) {                  // 如果获取不到__builtins__值        PyObject *bimod = PyImport_ImportModule("builtins");                // 导入builtins,先从全局中查找,找不到则导入        if (bimod == NULL) {            Py_FatalError("Failed to retrieve builtins module");        }        if (PyDict_SetItemString(d, "__builtins__", bimod) < 0) {           // 设置到__builtins__ 属性中            Py_FatalError("Failed to initialize __main__.__builtins__");        }        Py_DECREF(bimod);    }    /* Main is a little special - imp.is_builtin("__main__") will return     * False, but BuiltinImporter is still the most appropriate initial     * setting for its __loader__ attribute. A more suitable value will     * be set if __main__ gets further initialized later in the startup     * process.     */    loader = PyDict_GetItemString(d, "__loader__");                         // 获取__loader__属性    if (loader == NULL || loader == Py_None) {                              // 获取不到        PyObject *loader = PyObject_GetAttrString(interp->importlib,                                                  "BuiltinImporter");       // 获取importlib的BuiltinImporter属性        if (loader == NULL) {            Py_FatalError("Failed to retrieve BuiltinImporter");        }        if (PyDict_SetItemString(d, "__loader__", loader) < 0) {            // 设置该属性            Py_FatalError("Failed to initialize __main__.__loader__");        }        Py_DECREF(loader);    }}

main模块就是作为主程序运行的Python模块,执行完成后,继续执行

if (!Py_NoSiteFlag)        initsite(); /* Module site */

initsite函数就是导入site-packages中存在的Python的模块,

/* Import the site module (not into __main__ though) */static voidinitsite(void){    PyObject *m;    m = PyImport_ImportModule("site");                              // 导入site模块    if (m == NULL) {        fprintf(stderr, "Failed to import the site module\n");        PyErr_Print();        Py_Finalize();        exit(1);    }    else {        Py_DECREF(m);    }}

查看PyImport_ImportModule函数,

PyObject *PyImport_ImportModule(const char *name){    PyObject *pname;    PyObject *result;    pname = PyUnicode_FromString(name);    if (pname == NULL)        return NULL;    result = PyImport_Import(pname);    Py_DECREF(pname);    return result;}...PyObject *PyImport_Import(PyObject *module_name){    static PyObject *silly_list = NULL;    static PyObject *builtins_str = NULL;    static PyObject *import_str = NULL;    PyObject *globals = NULL;    PyObject *import = NULL;    PyObject *builtins = NULL;    PyObject *modules = NULL;    PyObject *r = NULL;    /* Initialize constant string objects */    if (silly_list == NULL) {        import_str = PyUnicode_InternFromString("__import__");      // __import__属性值        if (import_str == NULL)            return NULL;        builtins_str = PyUnicode_InternFromString("__builtins__");  // __builtins__属性值        if (builtins_str == NULL)            return NULL;        silly_list = PyList_New(0);                                 // 设值list        if (silly_list == NULL)            return NULL;    }    /* Get the builtins from current globals */    globals = PyEval_GetGlobals();                                  // 获取全局变量    if (globals != NULL) {        Py_INCREF(globals);        builtins = PyObject_GetItem(globals, builtins_str);         // 从全局变量中获取内建类型        if (builtins == NULL)            goto err;    }    else {        /* No globals -- use standard builtins, and fake globals */        builtins = PyImport_ImportModuleLevel("builtins",                                              NULL, NULL, NULL, 0); // 导入builtins        if (builtins == NULL)            return NULL;        globals = Py_BuildValue("{OO}", builtins_str, builtins);    // 设值        if (globals == NULL)            goto err;    }    /* Get the __import__ function from the builtins */    if (PyDict_Check(builtins)) {        import = PyObject_GetItem(builtins, import_str);        if (import == NULL)            PyErr_SetObject(PyExc_KeyError, import_str);    }    else        import = PyObject_GetAttr(builtins, import_str);    if (import == NULL)        goto err;    /* Call the __import__ function with the proper argument list       Always use absolute import here.       Calling for side-effect of import. */    r = PyObject_CallFunction(import, "OOOOi", module_name, globals,                              globals, silly_list, 0, NULL);        // 导入模块    if (r == NULL)        goto err;    Py_DECREF(r);    modules = PyImport_GetModuleDict();                             // 获取interp的modules    r = PyDict_GetItem(modules, module_name);                       // 获取module_name对应的模块并返回    if (r != NULL)        Py_INCREF(r);  err:    Py_XDECREF(globals);    Py_XDECREF(builtins);    Py_XDECREF(import);    return r;}

此时获取导入的site,该文件位于Lib/site.py文件,该site.py文件在导入的时候,会执行main()函数,

def main():    """Add standard site-specific directories to the module search path.    This function is called automatically when this module is imported,    unless the python interpreter was started with the -S flag.    """    global ENABLE_USER_SITE    abs_paths()    known_paths = removeduppaths()    known_paths = venv(known_paths)    if ENABLE_USER_SITE is None:        ENABLE_USER_SITE = check_enableusersite()    known_paths = addusersitepackages(known_paths)    known_paths = addsitepackages(known_paths)    setquit()    setcopyright()    sethelper()    enablerlcompleter()    aliasmbcs()    execsitecustomize()    if ENABLE_USER_SITE:        execusercustomize()

该函数就是将site-packages中模块导入到sys.path中,其中执行的细节过程可以通过main函数的各个函数继续查看,至此,_Py_InitializeEx_Private初始化函数基本执行完成。

总结

Python启动后的基本的环境和变量已经基本上准备完成,相关内建函数导入,扩展的第三方模块导入完成,接下来就开始编译和执行Python脚本。

转载地址:https://blog.csdn.net/qq_33339479/article/details/81504536 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:Python3.5源码分析-内存管理
下一篇:Python3.5源码分析-内建模块builtins初始化

发表评论

最新留言

表示我来过!
[***.240.166.169]2024年04月13日 02时09分23秒