源码结构
下载Python的源码,解压,即可看到源码的目录结构。
奇怪:Python2.7.2根目录下的 README 文件中有 各个目录的说明,在 Python3.2.1根目录下的README文件中却没有相应的介绍了。
Include/
公有 头文件
Lib/
Python编写的模块
Modules/
C实现的模块
Objects/
内置对象类型的实现
PC/
Windows下构建Python的工程文件
PCbuild/
Parser/
解释器的 parser、tokenizer、input handling
Python/
解释器的 byte-compiler、interpreter
configure
shell 脚本
...
编译
在Windows下:PCbuild 下是VS2008 的工程文件
在linux下:
./configure
make
sudo make install
Python解释器
Python 解释器(可执行程序) 本身的代码非常简单,就是调用了 Py_Main 这个函数!
Python2.7
Python3.2
int Py_Main(int argc, char **argv)
int Py_Main(int argc, wchar_t **argv)
PyMain
PyRun_AnyFileExFlags
PyRun_InteractiveLoopFlags
PyRun_InteractiveOneFlags
PyParser_ParseFileFlagsEx
PyAST_Compile
PyEval_EvalCode
PyRun_SimpleFileExFlags
PyParser_ASTFromFile
PyAST_Compile
PyEval_EvalCode
调用主要有两个分支
交互式
执行脚本
二者最终都是
Parser
Compile
Eval
三个步骤。
源码
在python2中,使用的窄字符串,在python3中,使用宽字符串。所以python3的源码乍看起来复杂了好多。
源码:Modules/python.c
python 2.7
#include "Python.h"
int
main(int argc, char **argv)
{
...
return Py_Main(argc, argv);
}
python 3.2
#include "Python.h"
#include
#ifdef MS_WINDOWS
int
wmain(int argc, wchar_t **argv)
{
return Py_Main(argc, argv);
}
#else
int
main(int argc, char **argv)
{
wchar_t **argv_copy = (wchar_t **)PyMem_Malloc(sizeof(wchar_t*)*argc);
/* We need a second copies, as Python might modify the first one. */
wchar_t **argv_copy2 = (wchar_t **)PyMem_Malloc(sizeof(wchar_t*)*argc);
...
res = Py_Main(argc, argv_copy);
...
return res;
}
#endif
在 Windows 下,由于链接子系统和入口函数问题,所以有一个单独的 pythonw.exe :源码 PC/WinMain.c
#include "Python.h"
#define WIN32_LEAN_AND_MEAN
#include
int WINAPI wWinMain(
HINSTANCE hInstance, /* handle to current instance */
HINSTANCE hPrevInstance, /* handle to previous instance */
LPWSTR lpCmdLine, /* pointer to command line */
int nCmdShow /* show state of window */
)
{
return Py_Main(__argc, __wargv);
}
Python2中与此几乎完全相同,用__argv取代__wargv
Py_Main
源码定义在 Modules/main.c
int
Py_Main(int argc, wchar_t **argv)
{
...
Py_Initialize();
...
if (command) {
sts = run_command(command, &cf);
free(command);
} else if (module) {
sts = RunModule(module, 1);
}
else {
...
sts = -1; /* keep track of whether we've already run __main__ */
if (filename != NULL) {
sts = RunMainFromImporter(filename);
}
...
if (sts == -1)
sts = run_file(fp, filename, &cf);
}
...
if (Py_InspectFlag && stdin_is_interactive &&
(filename != NULL || command != NULL || module != NULL)) {
Py_InspectFlag = 0;
/* XXX */
sts = PyRun_AnyFileFlags(stdin, "", &cf) != 0;
}
...
Py_Finalize();
...
}
首先处理命令行参数
调用Py_Initialize();
执行
-c 指定的命令,run_command 中 调用PyRun_SimpleStringFlags(...)
-m 指定的模块,RunModule调用PyObject_Call(...)
文件名非空,则将文件作为__main__模块导入
run_file 调用PyRun_AnyFileExFlags(...)
PyRun_AnyFileFlags调用的也是PyRun_AnyFileExFlags(...)
调用Py_Finalize();
PyRun_AnyFileExFlags
源码:Python/pythonrun.c
/* Parse input from a file and execute it */
int
PyRun_AnyFileExFlags(FILE *fp, const char *filename, int closeit,
PyCompilerFlags *flags)
{
if (filename == NULL)
filename = "???";
if (Py_FdIsInteractive(fp, filename)) {
int err = PyRun_InteractiveLoopFlags(fp, filename, flags);
if (closeit)
fclose(fp);
return err;
}
else
return PyRun_SimpleFileExFlags(fp, filename, closeit, flags);
}
两个分支:
交互式
脚本文件
下面3个马甲都是直接调用的该函数:
PyRun_AnyFile(FILE *fp, const char *name)
PyRun_AnyFileEx(FILE *fp, const char *name, int closeit)
PyRun_AnyFileFlags(FILE *fp, const char *name, PyCompilerFlags *flags)
run_mod
前面分流的两个分支,最后又都会调用 run_mod 函数
static PyObject *
run_mod(mod_ty mod, const char *filename, PyObject *globals, PyObject *locals,
PyCompilerFlags *flags, PyArena *arena)
{
PyCodeObject *co;
PyObject *v;
co = PyAST_Compile(mod, filename, flags, arena);
if (co == NULL)
return NULL;
v = PyEval_EvalCode((PyObject*)co, globals, locals);
Py_DECREF(co);
return v;
}
python -c
简单看看 python -c "print('hello')" 这种命令行语句会发生什么?
首先从 Py_Main 看起,
Py_Main
解析命令行参数,发现 -c 选项,将命令行中后续内容作为 command 的内容。
设置 sys.argv[0] 为 -c
通过 run_command() 执行命令
int
Py_Main(int argc, wchar_t **argv)
{
...
wchar_t *command = NULL;
...
while ((c = _PyOS_GetOpt(argc, argv, PROGRAM_OPTS)) != EOF) {
if (c == 'c') {
size_t len;
len = wcslen(_PyOS_optarg) + 1 + 1;
command = (wchar_t *)malloc(sizeof(wchar_t) * len);
wcscpy(command, _PyOS_optarg);
command[len - 2] = '\n';
command[len - 1] = 0;
break;
}
...
}
...
if (command != NULL) {
/* Backup _PyOS_optind and force sys.argv[0] = '-c' */
_PyOS_optind--;
argv[_PyOS_optind] = L"-c";
}
...
if (command) {
sts = run_command(command, &cf);
free(command);
}
...
}
run_command
宽字符串command ==> 转换成unicode对象 ==> 转换成 bytes 对象 ==> 窄字符串
窄字符串传递到PyRun_SimpleStringFalgs
static int
run_command(wchar_t *command, PyCompilerFlags *cf)
{
PyObject *unicode, *bytes;
int ret;
unicode = PyUnicode_FromWideChar(command, -1);
bytes = PyUnicode_AsUTF8String(unicode);
Py_DECREF(unicode);
ret = PyRun_SimpleStringFlags(PyBytes_AsString(bytes), cf);
Py_DECREF(bytes);
return ret != 0;
}
这儿调用的PyRun_SimpleStringFlags将会调用PyRun_StringFlags进而将调用 run_mod,这又回到了前面所看到的代码。
参考