分类 python 下的文章

python多进程和多线程的效率

  • python多进程和多线程通过multiprocessing和threading两个模块实现,由于python是c写的,所以和C语言的多进程和多线程基本相同,唯一不同的是python多线程并没有利用多核cpu的并行处理能力,无论开启多少个线程,始终只占用一个核心的cpu利用率,原因在于GIL(全局解释器锁)限制了同一时刻只能有一个线程在运行,GIL有其历史原因,至今依然存在主要在于python本身运行效率远低于c,若需要多线程处理,直接调用c的接口即可,也可以采用python的多进程来处理。下面具体分析一下python多进程和多线程的效率孰优孰劣
  • 单核cpu
    多线程效率高于多进程
  • 多核cpu
    对于cpu密集型任务,多进程的效率高于多线程,对于IO密集型任务,当任务数超出核心一定数量后,多线程效率高于多进程

python pip安装

1. 下载pip源码

https://pypi.org/project/pip/#files

2. 安装setuptools

可参考Python MySQLdb 模块安装

3. 解压运行setup.py

python setup.py install

从c语言层分析python的实现原理

python作为一门开源的、跨平台的脚本语言,其底层全部用c来实现,下面从c语言的角度来分析python的执行过程

1. python解释器

编译python源码后,会在根目录生成python程序,此程序就是python脚本的解释器,python解释器主要由语法解析、编译和执行三个模块组成

2. python语法解析模块

python语法解析模块负责把python字符串或脚本文件根据其语法解析成c语言的数据结构

3. python编译模块

python编译模块负责把解析后的数据结构转换成虚拟机可执行的字节码对象PyCodeObject

4. python执行模块

python执行模块负责执行python字节码,通常也叫做python虚拟机

当执行python file时,python首先会判断file是否为字节码文件,通常字节码文件的扩展名为pyc或pyo,而普通python脚本为py,判断的逻辑如下:

if (maybe_pyc_file(fp, filename, ext, closeit)) {
        /* Try to run a pyc file. First, re-open in binary */
        if (closeit)
            fclose(fp);
        if ((fp = fopen(filename, "rb")) == NULL) {
            fprintf(stderr, "python: Can't reopen .pyc file\n");
            goto done;
        }
        /* Turn on optimization if a .pyo file is given */
        if (strcmp(ext, ".pyo") == 0)
            Py_OptimizeFlag = 1;
        v = run_pyc_file(fp, filename, d, d, flags);
    } else {
        v = PyRun_FileExFlags(fp, filename, Py_file_input, d, d,
                              closeit, flags);
    }

若是字节码文件,则直接调用执行模块来执行,执行函数如下:

PyAPI_FUNC(PyObject *) PyEval_EvalCodeEx(PyCodeObject *co,
                    PyObject *globals,
                    PyObject *locals,
                    PyObject **args, int argc,
                    PyObject **kwds, int kwdc,
                    PyObject **defs, int defc,
                    PyObject *closure);

若是脚本文件,则先调用解析模块再调用编译模块,执行函数如下:

PyAPI_FUNC(struct _mod *) PyParser_ASTFromString(const char *, const char *,
                                                 int, PyCompilerFlags *flags,
                                                 PyArena *);
PyAPI_FUNC(struct _mod *) PyParser_ASTFromFile(FILE *, const char *, int,
                                               char *, char *,
                                               PyCompilerFlags *, int *,
                                               PyArena *);
PyAPI_FUNC(PyCodeObject *) PyAST_Compile(struct _mod *, const char *,
                        PyCompilerFlags *, PyArena *);

通常很多人会认为,编译后的python脚本会执行很快,但事实并非如此,编译后的字节码文件只是省去了语法解析和编译两部分,所以执行效率和普通python脚本一样,只是加载速度相对较快。目前由于个人能力有限,暂时大概分析了python的执行过程,至于语法解析、编译和执行的细节,逻辑比较复杂,待内功修炼到一定层次,再一一揭开python的神秘面纱

Python MySQLdb 模块安装

1. 安装python

  • 下载源码(version>=2.3.4)

    https://www.python.org/downloads/source/

  • 编译安装

    CFLAGS="-O3 -fPIC" ./configure
    make && make install

2. 安装setuptools

  • 下载和python版本一致的egg

    https://pypi.python.org/pypi/setuptools/0.6c11

  • 执行egg

    chmod a+x setuptools-0.6c11-py2.7.egg
    sh ./setuptools-0.6c11-py2.7.egg

3. 安装MySQL-python

  • 下载源码

    https://pypi.python.org/pypi/MySQL-python/

  • 编译安装

    C_INCLUDE_PATH=/usr/local/include/python2.7
    export C_INCLUDE_PATH
    python setup.py build
    python setup.py.install

  • 验证

    python -c "import MySQLdb" && echo $?
    若上述命令返回0,则表明MySQLdb安装成功