编写Python的C扩展

最近做性能压测,接口都是文件协议,需要用Python生成大数据量的交易文件,涉及到一个生成11位不重复的账号,考虑用系统毫秒数加序列来生成,但是光系统毫秒数都已经13位了,位数不够用,想到可以用62进制来压缩位数,结果用Python的写法,调用1000W次,需要68秒,就想到了可以用C来进行扩展。

首先在Clion中新建一个C Library ,type选shared,standard选C99

然后在CMakeLists.txt文件中加入python头文件的路径:

include_directories(/Library/Frameworks/Python.framework/Versions/3.7/include/python3.7m)

在library.c文件中写入代码:


#include 

/*引用python的头文件*/


char * zip(long long dec_number, char *result) {

    char* r = result;
    char baseList[] = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
    char tmp[] = "00000000000";
    int i = 0;
    while (i < 11) {
        long long x, y;
        x = dec_number /62;
        y = dec_number % 62;
        if (x <1) {
            tmp[10-i] = baseList[dec_number];
            i ++;
            break;

        } else {
            tmp[10-i] = baseList[y];
            dec_number = x;
            i ++;
        }

    }

    for (int j = 0; j < i ; ++j) {
        *r++ = tmp[11-i+j];
    }
    *r++ = '\0';
    return result;
}

int getNumber(char p) {
    if (p >= 97 && p <= 122) {
        return p - 87;
    } else if (p >= 65 && p <= 90) {
        return p - 29;
    } else
        return p - 48;
}

long long myPow(int x, int y) {
    long long result = x;
    if (y == 0) {
        result = 1;
    }
    else {
        for (int i = 0; i < y-1; ++i) {
            result *= x ;
        }
    }
    return result;
}


long long unzip(char *number_62) {
    long long result = 0;
    int number_len = strlen(number_62);

    for (int i = 0; i < number_len; ++i) {
        result += getNumber(number_62[i]) * myPow(62, number_len-i-1);
    }

    return result;
}

static PyObject * zipString_zip(PyObject *self, PyObject *args){
    /*参数转换,把Python传入的参数转换成c的参数类型*/
    long long num;
    if(!(PyArg_ParseTuple(args, "L", &num))){
        return NULL;
    }
    char result[11];
    result = zip(num, result);
    //把c函数的返回值转换成Python的数据类型
    return Py_BuildValue("s", result);
}


static PyObject * zipString_unzip(PyObject *self, PyObject *args){
    char *s;
    if(!(PyArg_ParseTuple(args, "z", &s))){
        return NULL;
    }
    long long p = unzip(s);
    return Py_BuildValue("L", p);
}

//将函数添加到Python模块中,以便可以在Python中导入
static PyMethodDef zipStringMethods[]={
        {"zip", zipString_zip, METH_VARARGS},
        {"unzip", zipString_unzip, METH_VARARGS},
        {NULL, NULL},
};

static struct  PyModuleDef zipStringModule = {
        PyModuleDef_HEAD_INIT,
        "zipString",
        NULL,
        -1,
        zipStringMethods
};

//创建模块
void PyInit_zipString(){
    PyModule_Create(& zipStringModule);
}

编写setup.py文件,用于打包和安装:

from distutils.core import setup, Extension

MOD = 'zipString'
setup(name=MOD, ext_modules=[Extension(MOD, sources=['library.c'], extra_compile_args=["-std=c99"])])

最后在终端中输入:

cd ~/CLionProjects/zipString/
sudo python3 setup.py build
sudo python3 setup.py install

然后就可以愉快的在Python中调用啦:

import zipString


print(zipString.zip(1546335593004))
print(zipString.unzip("rdTsyNm"))

控制台输出:

编写Python的C扩展_第1张图片

现在再在python中调用这个压缩1000W次,只需要3秒钟啦

你可能感兴趣的:(Python,C扩展)