• 使用C语言扩展Python提供性能


    python底层是用c写的,c本身是一个非常底层的语言,所以它做某些事情的效率肯定会比上层语言高一些。

    比如有些自动化测试用的python库,会对系统的UI进行一些捕获,点击之类的操作,这必然要用到c,实际上这些库就是用c来扩展的。先用c写一些调用系统UI的接口,然后把它封装成python方法。

    下面是一个简单的用C来扩展python的例子:

    test.c

    #include "Python.h"
    static PyObject *pr_getsum(PyObject *self,PyObject *args)
    {
        int n,m;
        if(!PyArg_ParseTuple(args,"ii",&n,&m))
        return NULL;
        return Py_BuildValue("i",m+n);
    }
    
    static PyMethodDef PrMethods[]={
    {"getsum",pr_getsum,METH_VARARGS,"get the sum"},
    {NULL,NULL,0,NULL}
    };
    
    void initpr(void)
    {
        (void) Py_InitModule("pr",PrMethods);
    }

    上面3个部分缺一不可,主要有:

    1. 导出函数:需要注意的是PyArg_ParseTuple(args,"ii",&n,&m)) 这一句,表示python要传入的参数。

                      "i" 表示整数,"d"表示浮点数,“s"表示字符串。

                      要传入2个参数就写"ii","dd","is"等,也可以用多种选择"is|ii"表示第一个参数是整数,第二个可以是字符串或整数

    2. 方法列表:PyMethodDef的成员一次表示"方法名,导出函数,参数传递方式,方法描述“

    3. 初始化函数:必须以init开头

     然后是编写setup.py文件,与上面的test.c文件在一个目录下

    from distutils.core import setup,Extension
    
    module = Extension('pr',sources=['test.c'])
    setup(name='pr test',version='1.0',ext_modules=[module])

    然后执行命令就可以了

    python setup.py build

    结束后可以看到生成了一个build目录,里面会有2个文件test.o和pr.so。我们需要用到的是pr.so文件。

    可以把pr.so文件放到python的site_packages目录下,或者把pr.so所在的目录添加到sys.path里,就可以在python里直接调用了

    import pr
    print pr.getsum(2,3) 

    需要注意的是,在windows上运行python setup.py build的时候可能会报错error: Unable to find vcvarsall.bat 。 这个就自己在google上搜下解决方法吧,linux和mac上应该是可以直接运行的。

    使用ctypes调用c语言函数

    还是上面的例子,我们要求2个数的和。那么在windows上可以这样写

    
    __declspec(dllexport) int
    add(int num1, int num2)
    {
        return num1 + num2;
    }

    然后是把这个文件编译成动态链接库,这时候需要用到cl命令

    cl命令需要安装visual studio,如果已经安装了请按这个方法来配置环境变量http://hi.baidu.com/xiaoma/item/94c649dc4bc5dae3795daac2

    然后运行

    cl -LD test.c -o test.dll

    可以在当前目录下生成一个test.dll文件,这个就是我们要用的。

    然后在python文件里就可以直接使用了

    from ctypes import *
    
    def main():
        libtest = cdll.LoadLibrary('test.dll')
        print libtest.add(2,3)
    
    if __name__ == '__main__':
        main()

     这个方法在macos x上貌似不行,有待考究

  • 相关阅读:
    替代或者与 Redis 配合存储十亿级别列表的数据.
    Python中高层次的数据结构,动态类型和动态绑定,使得它非常适合于快速应用开发,也适合于作为胶水语言连接已有的软件部件。
    伪类 伪元素
    模块与你的主业务代码是应该解耦的
    MarkdownPad
    长度区间校验公共方法,引入棉花糖
    不可见字符
    eval is not a function
    for (const k in v){ 变量作用域
    爬虫站点的历史入库数据,对入库数据的无外网处理,幂等操作;反之,不幂等操作
  • 原文地址:https://www.cnblogs.com/streakingBird/p/4062893.html
Copyright © 2020-2023  润新知