Python Source Code Analysis (1)

本文详细剖析了Python解释器的主要入口函数Py_Main。首先介绍了变量和参数,接着分析了选项c和m的处理,以及其他选项的行为。Python会根据命令行参数进行初始化,如设置警告选项、解析环境变量、处理输入输出缓冲等。如果遇到帮助或版本选项,程序会立即终止。在确定执行模式后,Python会启动交互式模式、运行模块或脚本文件。如果既没有命令也没有模块,Python将进入交互模式。最后,文章对重新运行交互模式和清理工作进行了简要说明,为后续深入理解Python启动流程奠定了基础。
摘要由CSDN通过智能技术生成

In this post, we will take a dissecion of source code of Python.

To benefit the simplicity and meanwhile follow the most recent functionnalities, I choose Python 3.6.9 to do the analysis.

In the last post, the entry of Python is found, so it’s time to look at it!

Py_Main - the Python Main function

According to C89 standard, in a C function, all the variables should be declared at the beginning. So, we can take a look at those variables.

Variables

The variables are listed below, though we’ll not explicite them at the moment.

    int c;
    int sts;
    wchar_t *command = NULL;
    wchar_t *filename = NULL;
    wchar_t *module = NULL;
    FILE *fp = stdin;
    char *p;
#ifdef MS_WINDOWS
    wchar_t *wp;
#endif
    int skipfirstline = 0;
    int stdin_is_interactive = 0;
    int help = 0;
    int version = 0;
    int saw_unbuffered_flag = 0;
    char *opt;
    PyCompilerFlags cf;
    PyObject *main_importer_path = NULL;
    PyObject *warning_option = NULL;
    PyObject *warning_options = NULL;

Arguments

Then, after listing and initializing all variables, Python will try to find flags in the arguments.

First, Python tries to find some options which are needed by some initializations.

/* Hash randomization needed early for all string operations
   (including -W and -X options). */
while ((c = _PyOS_GetOpt(argc, argv, PROGRAM_OPTS)) != EOF) {
   
    if (c == 'm' || c == 'c') {
   
        /* -c / -m is the last option: following arguments are
            not interpreter options. */
        break;
    }
    if (c == 'E') {
   
        Py_IgnoreEnvironmentFlag++;
        break;
    }
}

PROGRAM_OPTS is defined as BASE_OPTS, and #define BASE_OPTS L"bBc:dEhiIJm:OqRsStuvVW:xX:?" is at the header of main.c.

_PyOS_GetOpt is implemented in Python/getopt.c, which validates and returns argument option. If an option is not in PROGRAM_OPTS, a _ will be returned. It will not accept --argument and returns a -1 if an argument with that form is found.

In these lines, only options E, m, c are detected:

  • if E is detected, the flag which leads to the negligence of PYTHONPATH, PYTHONHOME environment variables.
  • once m or c is detected, following parameters should be the name of module(for m option) or the command that will be executed(for c option). So we terminated this loop.

Then, Python gets the PYTHONMALLOC variables and tries to use it to setup allocators.

opt = Py_GETENV("PYTHONMALLOC");
if (_PyMem_SetupAllocators(opt) < 0) {
   
    fprintf(stderr,
            "Error in PYTHONMALLOC: unknown allocator \"%s\"!\n", opt);
    exit(1);
}

Valid allocators are pymalloc, pymalloc_debug, malloc, malloc_debug and debug. If you’d like to get more about them, Objects/obmalloc.c is a good place.

And then Python does an initialization of Random module. In this module, PYTHONHASHSEED can be used to initialize random module. And it resets warning options, resets option parsing process to process all options.

_PyRandom_Init();

PySys_ResetWarnOptions();
_PyOS_ResetGetOpt();

while ((c = _PyOS_GetOpt(argc, argv, PROGRAM_OPTS)) != EOF) {
   
    // ...
}

We finally enter the period to parse all arguments. They will be explicited in order.

Option c

-c cmd : program passed in as string (terminates option list)`

if (c == 'c') {
   
    size_t len;
    /* -c is the last option; following arguments
        that look like options are left for the
        command to interpret. */

    len = wcslen(_PyOS_optarg) + 1 + 1;
    command = (wchar_t *)PyMem_RawMalloc(sizeof(wchar_t) * len);
    if (command == NULL)
        Py_FatalError(
            "not enough memory to copy -c argument");
    wcscpy(command, _PyOS_optarg);
    command[len - 2] = '\n';
    command[len - 1] = 0;
    break;
}

If we encounter an c option, all other arguments will be neglected. The following argument will be parsed as the commands to be run.

Option m

-m mod : run library module as a script (terminates option list)

if (c == 'm') {
   
    /* -m is the last option; following arguments
        that look like options are left for the
        module to interpret. */
    module = _PyOS_optarg;
    break;
}

If we encounter an m option, all other arguments will be neglected. The following argument will be parsed as the module to be run.

Other options

-B     : don't write .py[co] files on import; also PYTHONDONTWRITEBYTECODE=x
-d     : debug output from parser; also PYTHONDEBUG=x
-E     : ignore PYTHON* environment variables (such as PYTHONPATH)
-h     : print this help message and exit (also --help)
-i     : inspect interactively after running script; forces a prompt even
         if stdin does not appear to be a terminal; also PYTHONINSPECT=x
-O     : optimize generated bytecode slightly; also PYTHONOPTIMIZE=x
-OO    : remove doc-strings in addition to the -O optimizations
-R     : use a pseudo-random salt to make hash() values of various types be
         unpredictable between separate invocations of the interpreter, as
         a defense against denial-of-service attacks
-Q arg : division options: -Qold (default), -Qwarn, -Qwarnall, -Qnew
-s     : don't add user site directory to sys.path; also PYTHONNOUSERSITE
-S     : don't imply 'import site' on initialization
-t     : issue warnings about inconsistent tab usage (-tt: issue errors)
-u     : unbuffered binary stdout and stderr; also PYTHONUNBUFFERED=x
         see man page for details on internal buffering relating to '-u'
-v     : verbose (trace import statements); also PYTHONVERBOSE=x
         can be supplied multiple times to increase verbosity
-V     : print the Python version number and exit (also --version)
-W arg : warning control; arg is action:message:category:module:lineno
         also PYTHONWARNINGS=arg
-x     : skip first line o
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
这些是来自 SonarQube 静态代码分析工具的警告和建议。我将逐个解释它们的含义: 1. "SCM provider autodetection failed. Please use "sonar.scm.provider" to define SCM of your project, or disable the SCM Sensor in the project settings." 这表示 SonarQube 无法自动检测到你的项目的源代码管理(SCM)提供者。你需要手动设置 "sonar.scm.provider" 参数来定义你的项目的 SCM,或在项目设置中禁用 SCM 传感器。 2. "Your code is analyzed as compatible with python 2 and 3 by default. This will prevent the detection of issues specific to python 2 or python 3. You can get a more precise analysis by setting a python version in your configuration via the parameter "sonar.python.version"." 这表示默认情况下,你的代码被分析为与 Python 2 和 3 兼容。这将阻止检测特定于 Python 2 或 Python 3 的问题。你可以通过在配置中设置 Python 版本参数 "sonar.python.version" 来获得更精确的分析。 3. "There are problems with file encoding in the source code. Please check the scanner logs for more details." 这表示源代码中存在文件编码问题。请检查扫描器日志以获取更多详细信息。 4. "24 unanalyzed C files were detected in this project during the last analysis. C cannot be analyzed with your current SonarQube edition. Please consider upgrading to Developer Edition to find Bugs, Code Smells, Vulnerabilities and Security Hotspots in this file." 这表示在最近的分析中检测到了 24 个未分析的 C 文件。你当前使用的 SonarQube 版本无法分析 C 语言。请考虑升级到 Developer Edition,以便在该文件中查找错误、代码异味、漏洞和安全热点。 希望这些解释对你有所帮助!如果你需要进一步的解释或有其他问题,请随时提问。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值