Python3.5源码分析-sys模块及site模块导入

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_33339479/article/details/81504536

Python3源码分析

本文环境python3.5.2。
参考书籍<<Python源码剖析>>
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;          
}   

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)     // 设置到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_t
PyOS_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
}

void
PyOS_InitInterrupts(void)
{
    PyObject *m = PyImport_ImportModule("_signal");     // 导入_signal
    if (m) {
        Py_DECREF(m);
    }
}

...

static void
initsigs(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 void
initmain(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 void
initsite(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脚本。

猜你喜欢

转载自blog.csdn.net/qq_33339479/article/details/81504536