本文共 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 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!