Python 扩展技术总结(转)

p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; line-height: 38.0px; font: 24.0px "PingFang SC Semibold"; color: #2c3033 }
p.p2 { margin: 0.0px 0.0px 0.0px 0.0px; line-height: 38.0px; font: 14.0px Times; color: #bbbbbb }
p.p4 { margin: 0.0px 0.0px 16.0px 0.0px; text-align: justify; line-height: 26.0px; font: 18.0px "PingFang SC"; color: #4f4f4f }
p.p5 { margin: 0.0px 0.0px 16.0px 0.0px; text-align: justify; line-height: 26.0px; font: 18.0px "PingFang SC"; color: #3333ff }
p.p6 { margin: 0.0px 0.0px 16.0px 0.0px; text-align: justify; line-height: 26.0px; font: 19.0px "PingFang SC"; color: #4f4f4f; background-color: #ffffff }
p.p7 { margin: 0.0px 0.0px 16.0px 0.0px; text-align: justify; line-height: 26.0px; font: 19.0px Arial; color: #ff0000 }
p.p8 { margin: 0.0px 0.0px 16.0px 0.0px; text-align: justify; line-height: 26.0px; font: 16.0px "PingFang SC"; color: #4f4f4f; background-color: #ffffff; min-height: 22.0px }
p.p9 { margin: 0.0px 0.0px 0.0px 0.0px; line-height: 11.0px; font: 9.0px Verdana; color: #6795b5; background-color: #f8f8f8 }
p.p10 { margin: 0.0px 0.0px 0.0px 0.0px; line-height: 11.0px; font: 9.0px Verdana; color: #c0c0c0; min-height: 11.0px }
p.p16 { margin: 0.0px 0.0px 0.0px 0.0px; line-height: 25.0px; font: 18.0px "PingFang SC Semibold"; color: #454545; background-color: #ffffff }
p.p17 { margin: 0.0px 0.0px 16.0px 0.0px; text-align: justify; line-height: 26.0px; font: 19.0px Arial; color: #3333ff; background-color: #ffffff }
p.p18 { margin: 0.0px 0.0px 16.0px 0.0px; text-align: justify; line-height: 26.0px; font: 18.0px "PingFang SC"; color: #4f4f4f; background-color: #ffffff }
p.p19 { margin: 0.0px 0.0px 16.0px 0.0px; text-align: justify; line-height: 26.0px; font: 18.0px Arial; color: #ff0000 }
p.p23 { margin: 0.0px 0.0px 16.0px 0.0px; text-align: justify; line-height: 26.0px; font: 19.0px "PingFang SC"; color: #3333ff; background-color: #ffffff }
p.p24 { margin: 0.0px 0.0px 0.0px 0.0px; line-height: 22.0px; font: 16.0px "PingFang SC"; color: #454545; background-color: #ffffff }
p.p25 { margin: 0.0px 0.0px 16.0px 0.0px; text-align: justify; line-height: 22.0px; font: 19.0px "PingFang SC"; color: #3333ff; background-color: #ffffff }
p.p26 { margin: 0.0px 0.0px 0.0px 0.0px; text-align: justify; line-height: 16.0px; font: 18.0px "PingFang SC"; color: #000000; background-color: #ffffff }
p.p27 { margin: 0.0px 0.0px 0.0px 0.0px; text-align: justify; line-height: 16.0px; font: 18.0px "PingFang SC"; color: #ff0000; background-color: #ffffff }
p.p31 { margin: 0.0px 0.0px 0.0px 0.0px; line-height: 22.0px; font: 16.0px "PingFang SC"; color: #454545; background-color: #ffffff; min-height: 22.0px }
p.p32 { margin: 0.0px 0.0px 0.0px 0.0px; line-height: 22.0px; font: 19.0px "PingFang SC"; color: #454545; background-color: #ffffff }
p.p33 { margin: 0.0px 0.0px 16.0px 0.0px; text-align: justify; line-height: 26.0px; font: 19.0px "PingFang SC"; color: #339999; background-color: #ffffff }
p.p34 { margin: 0.0px 0.0px 16.0px 0.0px; text-align: justify; line-height: 26.0px; font: 19.0px Arial; color: #4f4f4f; background-color: #ffffff }
p.p35 { margin: 0.0px 0.0px 16.0px 0.0px; text-align: justify; line-height: 26.0px; font: 19.0px "PingFang SC"; color: #4f4f4f }
p.p36 { margin: 0.0px 0.0px 16.0px 0.0px; text-align: justify; line-height: 26.0px; font: 19.0px Arial; color: #ff0000; background-color: #ffffff }
p.p38 { margin: 0.0px 0.0px 0.0px 0.0px; line-height: 22.0px; font: 14.0px Courier; color: #000000; background-color: #f0f0f0; min-height: 17.0px }
p.p39 { margin: 0.0px 0.0px 0.0px 0.0px; line-height: 22.0px; font: 16.0px "PingFang SC"; color: #000000; min-height: 22.0px }
p.p40 { margin: 0.0px 0.0px 0.0px 0.0px; line-height: 25.0px; font: 18.0px "PingFang SC"; color: #000000; background-color: #ffffff }
p.p41 { margin: 0.0px 0.0px 0.0px 0.0px; line-height: 22.0px; font: 18.0px "PingFang SC"; color: #454545 }
p.p42 { margin: 0.0px 0.0px 16.0px 0.0px; text-align: justify; line-height: 26.0px; font: 18.0px "PingFang SC"; color: #ff0000; background-color: #ffffff }
p.p43 { margin: 0.0px 0.0px 0.0px 0.0px; line-height: 22.0px; font: 18.0px Verdana; color: #c0c0c0; background-color: #f8f8f8 }
p.p47 { margin: 0.0px 0.0px 16.0px 0.0px; line-height: 30.0px; font: 18.0px "PingFang SC"; color: #4f4f4f; background-color: #ffffff }
p.p48 { margin: 0.0px 0.0px 24.0px 0.0px; line-height: 22.0px; font: 16.0px "PingFang SC"; color: #454545; background-color: #ffffff; min-height: 22.0px }
p.p49 { margin: 0.0px 0.0px 16.0px 0.0px; text-align: justify; line-height: 26.0px; font: 18.0px "PingFang SC Semibold"; color: #4f4f4f; background-color: #ffffff }
p.p50 { margin: 0.0px 0.0px 16.0px 0.0px; line-height: 30.0px; font: 18.0px "PingFang SC Semibold"; color: #4f4f4f; background-color: #ffffff }
p.p52 { margin: 0.0px 0.0px 0.0px 0.0px; line-height: 25.0px; font: 18.0px "PingFang SC"; color: #454545 }
li.li3 { margin: 0.0px 0.0px 0.0px 0.0px; line-height: 24.0px; font: 14.0px "Helvetica Neue"; color: #bbbbbb }
li.li11 { margin: 0.0px 0.0px 0.0px 0.0px; line-height: 18.0px; font: 12.0px "Courier New"; color: #808080; background-color: #ffffff }
li.li12 { margin: 0.0px 0.0px 0.0px 0.0px; line-height: 18.0px; font: 12.0px "Courier New"; color: #808080; background-color: #f8f8f8 }
li.li13 { margin: 0.0px 0.0px 0.0px 0.0px; line-height: 18.0px; font: 12.0px "Courier New"; color: #000000; background-color: #f8f8f8 }
li.li14 { margin: 0.0px 0.0px 0.0px 0.0px; line-height: 18.0px; font: 12.0px "Courier New"; color: #000000; background-color: #ffffff }
li.li15 { margin: 0.0px 0.0px 0.0px 0.0px; line-height: 18.0px; font: 12.0px "Courier New"; color: #5c5c5c; background-color: #f8f8f8; min-height: 14.0px }
li.li20 { margin: 0.0px 0.0px 0.0px 0.0px; line-height: 18.0px; font: 12.0px "Courier New"; color: #008200; background-color: #ffffff }
li.li21 { margin: 0.0px 0.0px 0.0px 0.0px; line-height: 18.0px; font: 12.0px "Courier New"; color: #008200; background-color: #f8f8f8 }
li.li22 { margin: 0.0px 0.0px 0.0px 0.0px; line-height: 18.0px; font: 12.0px "PingFang SC"; color: #008200; background-color: #ffffff }
li.li28 { margin: 0.0px 0.0px 0.0px 0.0px; line-height: 18.0px; font: 14.0px "Courier New"; color: #006699; background-color: #ffffff }
li.li29 { margin: 0.0px 0.0px 0.0px 0.0px; line-height: 18.0px; font: 14.0px "Courier New"; color: #006699; background-color: #f8f8f8 }
li.li30 { margin: 0.0px 0.0px 0.0px 0.0px; line-height: 18.0px; font: 12.0px "Courier New"; color: #0000ff; background-color: #ffffff }
li.li37 { margin: 0.0px 0.0px 0.0px 0.0px; line-height: 18.0px; font: 12.0px "Courier New"; color: #006699; background-color: #f8f8f8 }
li.li44 { margin: 0.0px 0.0px 0.0px 0.0px; line-height: 18.0px; font: 18.0px "Courier New"; color: #008200; background-color: #f8f8f8 }
li.li45 { margin: 0.0px 0.0px 0.0px 0.0px; line-height: 18.0px; font: 18.0px "Courier New"; color: #000000; background-color: #f8f8f8 }
li.li46 { margin: 0.0px 0.0px 0.0px 0.0px; line-height: 18.0px; font: 18.0px "Courier New"; color: #0000ff; background-color: #f8f8f8 }
li.li51 { margin: 0.0px 0.0px 0.0px 0.0px; line-height: 18.0px; font: 18.0px "Courier New"; color: #808080; background-color: #f8f8f8 }
li.li52 { margin: 0.0px 0.0px 0.0px 0.0px; line-height: 25.0px; font: 18.0px "PingFang SC"; color: #454545 }
span.s1 { font: 24.0px "PingFang SC" }
span.s2 { font: 14.0px "Songti SC"; color: #78909c }
span.s3 { color: #78909c }
span.s4 { }
span.s5 { font: 14.0px "Songti SC" }
span.s6 { font: 18.0px Arial; background-color: #ffffff }
span.s7 { background-color: #ffffff }
span.s8 { font: 18.0px Arial }
span.s9 { font: 18.0px Arial; color: #4f4f4f }
span.s10 { font: 19.0px Arial }
span.s11 { color: #4f4f4f }
span.s12 { color: #c0c0c0 }
span.s13 { color: #6795b5 }
span.s14 { color: #000000 }
span.s15 { color: #2e8b57 }
span.s16 { color: #2e8b57 }
span.s17 { font: 14.0px "Courier New"; color: #006699 }
span.s18 { color: #008200 }
span.s19 { font: 12.0px "PingFang SC"; color: #008200 }
span.s20 { font: 18.0px "PingFang SC" }
span.s21 { font: 19.0px "PingFang SC" }
span.s22 { font: 12.0px "PingFang SC" }
span.s23 { font: 14.0px "Courier New"; color: #006699 }
span.s24 { color: #0000ff }
span.s25 { font: 12.0px "Courier New" }
span.s26 { font: 12.0px "Courier New" }
span.s27 { font: 12.0px "Courier New"; color: #000000 }
span.s28 { font: 19.0px "PingFang SC"; color: #6795b5 }
span.s29 { font: 19.0px Arial; color: #6795b5 }
span.s30 { color: #3333ff }
span.s31 { font: 19.0px Arial; color: #3333ff }
span.s32 { font: 14.0px Courier; color: #c7254e; background-color: #f9f2f4 }
span.s33 { font: 18.0px Times }
span.s34 { color: #000000 }
span.s35 { font: 12.0px "PingFang SC"; color: #000000 }
span.s36 { font: 19.0px Arial; color: #4f4f4f }
span.s37 { font: 19.0px Arial; background-color: #ffffff }
span.s38 { color: #ff0000; background-color: #ffffff }
span.s39 { font: 19.0px Arial; color: #ff0000 }
span.s40 { font: 14.0px "Courier New" }
span.s41 { font: 14.0px "Courier New" }
span.s42 { font: 16.0px "PingFang SC"; background-color: #ffffff }
span.s43 { font: 18.0px "Courier New"; color: #000000 }
span.s44 { background-color: #ffffff }
ol.ol1 { list-style-type: decimal }
ul.ul1 { list-style-type: none }

一般来说,所有能被整合或导入到其他Python脚本中的代码,都可以称为扩展。你可以用纯Python来写扩展,也可以用C/C++之类的编译型语言来写扩展,甚至可以用java,C都可以来写 python扩展。Python的一大特点是,扩展和解释器之间的交互方式域普通的Python模块完全一样,Python的模块导入机制非常抽象,抽象到让使用模块的代码无法了解到模块的具体实现细节。

Python进行扩展的主要原因有三点:(1)添加额外的Python语言的核心部分没有提供的功能 (2)为了提升性能瓶颈的效率(3)保持专有源代码私密,把一部分代码从Python转到编译语言可以保持专有源代码私密

方法一:利用C API进行C扩展

这种方法是最基本的,包括三个步骤:1.创建应用程序代码 2.利用样板来包装代码 3.编译1.创建一个Extest.c文件 包含两个C函数

Extest.c

[cpp] view plain copy

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #define BUFSIZE 10
  5. int fac(int n) {
  6. if (n < 2)
  7. return 1;
  8. return n * fac(n - 1);
  9. }
  10. //字符串反转
  11. char *reverse(char *s) {
  12. register char t;
  13. char *p = s;
  14. char *q = (s + (strlen(s) - 1));
  15. while (p < q) {
  16. t = *p;
  17. *p++ = *q;
  18. *q-- = t;
  19. }
  20. return s;
  21. }

2.用样板来包装你的代码

使用样板分为4步:

1.添加Python的头文件

2.为每一个模块的每个函数增加一个形如PyObject* Module_func()的包装函数

3.为每一个模块增加一个形如PyMethodDef ModuleMethods[]的数组

4.增加模块初始化函数 void initModule()

第二步的处理需要一些技巧,你需要为所有想Python环境访问的函数增加一个静态函数。函数的返回值类型为 PyObject*,在Python的C语言扩展接口中,大部分函数都有一个或者多个参数为PyObject指针类型,并且返回值也大都为PyObject指针. 包装函数的用处是先把Python的值传递给C,然后调用C函数把函数的计算结果转换成Python 对象,然后返回给Python

第三步每一个数组都包含一个 函数信息,包括函数Python的名字,相应的包装函数的名字以及一个METH_VARARGS常量(表示参数以元组的形式传入)

Extest.c

[cpp] view plain copy

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include "Python.h"      //包含python头文件
  5. #define BUFSIZE 10
  6. int fac(int n) {
  7. if (n < 2)
  8. return 1;
  9. return n * fac(n - 1);
  10. }
  11. char *reverse(char *s) {
  12. register char t;
  13. char *p = s;
  14. char *q = (s + (strlen(s) - 1));
  15. while (p < q) {
  16. t = *p;
  17. *p++ = *q;
  18. *q-- = t;
  19. }
  20. return s;
  21. }
  22. //fac函数的包装函数
  23. static PyObject *
  24. Extest_fac(PyObject *self, PyObject *args) {
  25. int num;
  26. if (!(PyArg_ParseTuple(args, "i", &num))) {
  27. return NULL;
  28. }
  29. return (PyObject *)Py_BuildValue("i", fac(num));
  30. }
  31. //reverse函数的包装函数
  32. static PyObject *
  33. Extest_doppel(PyObject *self, PyObject *args) {
  34. char *orignal;
  35. char *reversed;
  36. PyObject * retval;
  37. if (!(PyArg_ParseTuple(args, "s", &orignal))) {
  38. return NULL;
  39. }
  40. retval = (PyObject *)Py_BuildValue("ss", orignal, reversed=reverse(strdup(orignal)));
  41. free(reversed);
  42. return retval;
  43. }
  44. //为模块创建一个函数信息的数组
  45. static PyMethodDef
  46. ExtestMethods[] = {
  47. {"fac", Extest_fac, METH_VARARGS},
  48. {"doppel", Extest_doppel, METH_VARARGS},
  49. };
  50. //增加模块初始化函数
  51. void initExtest() {
  52. Py_InitModule("Extest", ExtestMethods);
  53. }

在编译阶段需要创建一个setup.py,通过setup.py来编译和链接代码。这一步完成后就就可以直接导入这个扩展的模块了.在setup.py中需要导入distutils包。首先你要为每一个扩展创建一个Extension实例,然后编译的操作主要由setup()函数来完成,它需要两个参数:一个名字参数表示要编译哪个东西,一个列表表示要编译的对象

setup.py

[cpp] view plain copy

  1. <pre name="code" class="python">from distutils.core import setup, Extension
  2. MOD = ‘Extest‘
  3. setup(name=MOD, ext_modules=[
  4. Extension(MOD, sources=[‘Extest.c‘])])

运行setup.py   :执行命令 python setup.py build

执行的结果 是在当前目录中生成一个build 目录,在此目录下有一个Extest.so文件,然后就可以在脚本中import这个模块了

方法二:利用Ctypes进行C扩展

为了扩展Python,我们可以用C/C++编写模块,但是这要求对Python的底层有足够的了解,包括Python对象模

型、常用模块、引用计数等,门槛较高,且不方便利用现有的C库。而ctypes 则另辟蹊径,通过封装

dlopen/dlsym之类的函数,并提供对C中数据结构的包装/解包,让Python能够加载动态库、导出其中的函数直

接加以利用。

一个简单的实例:

这个例子直接利用ctypes使用C标准库函数而不用编写C代码,使用C标准库函数会产生优化效果

脚本一

[python] view plain copy

  1. import timeit
  2. import random
  3. def generate(num):
  4. while num:
  5. yield random.randrange(10)
  6. num -= 1
  7. print(timeit.timeit("sum(generate(999))", setup="from __main__ import generate", number=1000))

[python] view plain copy

  1. <span style="font-size:18px;color:#FF0000;">脚本二</span>
  2. import timeit
  3. from ctypes import cdll
  4. def generate_c(num):
  5. #Load standard C library
  6. libc = cdll.LoadLibrary("libc.so.6") #Linux
  7. # libc = cdll.msvcrt #Windows
  8. while num:
  9. yield libc.rand() % 10
  10. num -= 1
  11. print(timeit.timeit("sum(generate_c(999))", setup="from __main__ import generate_c", number=1000))

第一个脚本使用 Python的随机函数,运行时间约为1.067秒 第二个脚本使用C的随机函数 运行时间约为0.423秒

我们也利用Ctypes可以自己写模块导入使用:

步骤一创建应用程序代码

[cpp] view plain copy

  1. /* functions.c */
  2. #include "stdio.h"
  3. #include "stdlib.h"
  4. #include "string.h"
  5. /* http://rosettacode.org/wiki/Sorting_algorithms/Merge_sort#C */
  6. inline
  7. void merge(int *left, int l_len, int *right, int r_len, int *out)
  8. {
  9. int i, j, k;
  10. for (i = j = k = 0; i < l_len && j < r_len; )
  11. out[k++] = left[i] < right[j] ? left[i++] : right[j++];
  12. while (i < l_len) out[k++] = left[i++];
  13. while (j < r_len) out[k++] = right[j++];
  14. }
  15. /* inner recursion of merge sort */
  16. void recur(int *buf, int *tmp, int len)
  17. {
  18. int l = len / 2;
  19. if (len <= 1) return;
  20. /* note that buf and tmp are swapped */
  21. recur(tmp, buf, l);
  22. recur(tmp + l, buf + l, len - l);
  23. merge(tmp, l, tmp + l, len - l, buf);
  24. }
  25. /* preparation work before recursion */
  26. void merge_sort(int *buf, int len)
  27. {
  28. /* call alloc, copy and free only once */
  29. int *tmp = malloc(sizeof(int) * len);
  30. memcpy(tmp, buf, sizeof(int) * len);
  31. recur(buf, tmp, len);
  32. free(tmp);
  33. }
  34. int fibRec(int n){
  35. if(n < 2)
  36. return n;
  37. else
  38. return fibRec(n-1) + fibRec(n-2);
  39. }
  40. ~

步骤二:将它编译链接为.so文件

执行指令:gcc -Wall -fPIC -c functions.c

gcc -shared -o libfunctions.so functions.o

步骤三:在自己写的python脚本中使用这些库,下面的脚本分别用纯python的模块(输出时前面加了python),和我们导入的扩展(输出时前面加了C)模块来运行,对比其模块执行时间,

functions.py

[python] view plain copy

  1. from ctypes import *
  2. import time
  3. libfunctions = cdll.LoadLibrary("./libfunctions.so")
  4. def fibRec(n):
  5. if n<2 :
  6. return n
  7. else:
  8. return fibRec(n-1) + fibRec(n-2)
  9. start = time.time()
  10. fibRec(32)
  11. finish = time.time()
  12. print("Python: " + str(finish - start))
  13. #C Fibonacci
  14. start = time.time()
  15. x = libfunctions.fibRec(32)
  16. finish = time.time()
  17. print("C: " + str(finish - start))

functions2.py

[python] view plain copy

  1. from ctypes import *
  2. import time
  3. libfunctions = cdll.LoadLibrary("./libfunctions.so")
  4. #Python Merge Sort
  5. from random import shuffle, sample
  6. #Generate 9999 random numbers between 0 and 100000
  7. numbers = sample(range(100000), 9999)
  8. shuffle(numbers)
  9. c_numbers = (c_int * len(numbers))(*numbers)
  10. from heapq import merge
  11. def merge_sort(m):
  12. if len(m) <= 1:
  13. return m
  14. middle = len(m) // 2
  15. left = m[:middle]
  16. right = m[middle:]
  17. left = merge_sort(left)
  18. right = merge_sort(right)
  19. return list(merge(left, right))
  20. start = time.time()
  21. numbers = merge_sort(numbers)
  22. finish = time.time()
  23. print("Python: " + str(finish - start))
  24. #C Merge Sort
  25. start = time.time()
  26. libfunctions.merge_sort(byref(c_numbers), len(numbers))
  27. finish = time.time()
  28. print("C: " + str(finish - start))
  29. ~
  30. ~
  31. ~

运行结果

可以看出纯python模块的运行时间是我们写的扩展模块运行时间的十倍以上

方法三:利用Cython 进行C扩展 (参考Cython三分钟入门)

Cyhton 是一个用来快速生成 Python 扩展模块(extention module)的工具,它的语法是 python语言语法和 C 语言语法的混血。准确说 Cython 是单独的一门语言,专门用来写在 Python 里面import 用的扩展库。实际上 Cython 的语法基本上跟 Python 一致,而Cython 有专门的“编译器”;先将 Cython 代码转变成 C(自动加入了一大堆的 C-Python API),然后使用 C 编译器编译出最终的 Python可调用的模块。

要注意的一点是, Cython 是用来生成 C 扩展到而不是独立的程序的。所有的加速都是针对一个已经存在的 Python 应用的一个函数进行的。没有使用 C 或 Lisp 重写整个应用程序,也没有手写 C 扩展 。只是用一个简单的方法来整合 C 的速度和 C 数据类型到 Python函数中去

Cython 代码跟 Python 不一样,必须要编译。 编译经过两个阶段:(1) Cython 编译.pyx 文件为.c 文件 (2) C 编译器会把.c 文件编译成.so 文件.生成.so 文件后表示重写函数成功,可以在 python 代码中直接调用这个模块

Python代码

  1. #p1.py
  2. import math
  3. def great_circle(lon1,lat1,lon2,lat2):
  4. radius = 3956 #miles
  5. x = math.pi/180.0
  6. a = (90.0-lat1)*(x)
  7. b = (90.0-lat2)*(x)
  8. theta = (lon2-lon1)*(x)
  9. c = math.acos((math.cos(a)*math.cos(b)) +
  10. (math.sin(a)*math.sin(b)*math.cos(theta)))
  11. return radius*c

Python代码

  1. #p1_test.py
  2. import timeit
  3. lon1, lat1, lon2, lat2 = -72.345, 34.323, -61.823, 54.826
  4. num = 500000
  5. t = timeit.Timer("p1.great_circle(%f,%f,%f,%f)" % (lon1,lat1,lon2,lat2),
  6. "import p1")
  7. print "Pure python function", t.timeit(num), "sec"

Python代码

  1. # 测试结果
  2. Pure python function 2.25580382347 sec

Cython: 使用Python的math模块

Python代码

  1. #c1.pyx
  2. import math
  3. def great_circle(float lon1,float lat1,float lon2,float lat2):
  4. cdef float radius = 3956.0
  5. cdef float pi = 3.14159265
  6. cdef float x = pi/180.0
  7. cdef float a,b,theta,c
  8. a = (90.0-lat1)*(x)
  9. b = (90.0-lat2)*(x)
  10. theta = (lon2-lon1)*(x)
  11. c = math.acos((math.cos(a)*math.cos(b)) + (math.sin(a)*math.sin(b)*math.cos(theta)))
  12. return radius*c

Python代码

  1. # setup.py
  2. from distutils.core import setup
  3. from distutils.extension import Extension
  4. from Cython.Distutils import build_ext
  5. ext_modules=[
  6. Extension("c1",
  7. ["c1.pyx"])
  8. ]
  9. setup(
  10. name = "Demos",
  11. cmdclass = {"build_ext": build_ext},
  12. ext_modules = ext_modules
  13. )

python setup.py build_ext --inplace

Python代码

  1. #c1_test.py
  2. import timeit
  3. lon1, lat1, lon2, lat2 = -72.345, 34.323, -61.823, 54.826
  4. num = 500000
  5. t = timeit.Timer("c1.great_circle(%f,%f,%f,%f)" % (lon1,lat1,lon2,lat2),
  6. "import c1")
  7. print "Pure python function", t.timeit(num), "sec"

Python代码

  1. #执行结果:
  2. Pure python function 1.87078690529 sec

Cython:使用C的math库

Python代码

  1. #c2.pyx
  2. cdef extern from "math.h":
  3. float cosf(float theta)
  4. float sinf(float theta)
  5. float acosf(float theta)
  6. def great_circle(float lon1,float lat1,float lon2,float lat2):
  7. cdef float radius = 3956.0
  8. cdef float pi = 3.14159265
  9. cdef float x = pi/180.0
  10. cdef float a,b,theta,c
  11. a = (90.0-lat1)*(x)
  12. b = (90.0-lat2)*(x)
  13. theta = (lon2-lon1)*(x)
  14. c = acosf((cosf(a)*cosf(b)) + (sinf(a)*sinf(b)*cosf(theta)))
  15. return radius*c

Python代码

  1. #setup.py
  2. from distutils.core import setup
  3. from distutils.extension import Extension
  4. from Cython.Distutils import build_ext
  5. ext_modules=[
  6. Extension("c2",
  7. ["c2.pyx"],
  8. libraries=["m"]) # Unix-like specific
  9. ]
  10. setup(
  11. name = "Demos",
  12. cmdclass = {"build_ext": build_ext},
  13. ext_modules = ext_modules
  14. )

python setup.py build_ext --inplace

Python代码

  1. # c2_test.py  
  2. import timeit  
  3. lon1, lat1, lon2, lat2 = -72.345, 34.323, -61.823, 54.826  
  4. num = 500000  
  5. t = timeit.Timer("c2.great_circle(%f,%f,%f,%f)" % (lon1,lat1,lon2,lat2),  
  6.                        "import c2")  
  7. print "Pure python function", t.timeit(num), "sec"  

Python代码

  1. #执行结果  
  2. Pure python function 0.34069108963 sec   

Cython:使用C函数

Python代码

  1. #c3.pyx
  2. cdef extern from "math.h":
  3. float cosf(float theta)
  4. float sinf(float theta)
  5. float acosf(float theta)
  6. cdef float _great_circle(float lon1,float lat1,float lon2,float lat2):
  7. cdef float radius = 3956.0
  8. cdef float pi = 3.14159265
  9. cdef float x = pi/180.0
  10. cdef float a,b,theta,c
  11. a = (90.0-lat1)*(x)
  12. b = (90.0-lat2)*(x)
  13. theta = (lon2-lon1)*(x)
  14. c = acosf((cosf(a)*cosf(b)) + (sinf(a)*sinf(b)*cosf(theta)))
  15. return radius*c
  16. def great_circle(float lon1,float lat1,float lon2,float lat2,int num):
  17. cdef int i
  18. cdef float x
  19. for i from 0 <= i < num:
  20. x = _great_circle(lon1,lat1,lon2,lat2)
  21. return x

C-sharp代码

  1. #setup.py
  2. from distutils.core import setup
  3. from distutils.extension import Extension
  4. from Cython.Distutils import build_ext
  5. ext_modules=[
  6. Extension("c3",
  7. ["c3.pyx"],
  8. libraries=["m"]) # Unix-like specific
  9. ]
  10. setup(
  11. name = "Demos",
  12. cmdclass = {"build_ext": build_ext},
  13. ext_modules = ext_modules
  14. )

python setup.py build_ext --inplace

Python代码

  1. #c3_test.py
  2. import timeit
  3. lon1, lat1, lon2, lat2 = -72.345, 34.323, -61.823, 54.826
  4. num = 500000
  5. t = timeit.Timer("c2.great_circle(%f,%f,%f,%f)" % (lon1,lat1,lon2,lat2),
  6. "import c2")
  7. print "Pure python function", t.timeit(num), "sec"

Python代码

  1. #测试结果
  2. Pure python function 0.340164899826 sec

测试结论

Python代码

    • # python代码
    • Pure python function 2.25580382347 sec
    • # Cython,使用Python的math模块
    • Pure python function 1.87078690529 sec
    • # Cython,使用C的math库
    • Pure python function 0.34069108963 sec
    • # Cython,使用纯粹的C函数
    • Pure python function 0.340164899826 sec

注意事项:

通过cython扩展python 模块时出现“ImportError: No module named Cython.Build“的解决方法如下

pip install Cython

pip install fasttext

这个pip必须与当前python版本相一致

参考:  https://blog.csdn.net/u010786109/article/details/41825147#

p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; line-height: 38.0px; font: 24.0px "PingFang SC Semibold"; color: #2c3033 }
p.p2 { margin: 0.0px 0.0px 0.0px 0.0px; line-height: 38.0px; font: 14.0px "PingFang SC"; color: #bbbbbb }
p.p4 { margin: 0.0px 0.0px 16.0px 0.0px; text-align: justify; line-height: 26.0px; font: 16.0px "PingFang SC"; color: #4f4f4f }
li.li3 { margin: 0.0px 0.0px 0.0px 0.0px; line-height: 24.0px; font: 14.0px "Helvetica Neue"; color: #bbbbbb }
span.s1 { font: 24.0px "PingFang SC" }
span.s2 { color: #78909c }
span.s3 { }
ul.ul1 { list-style-type: none }

原文地址:https://www.cnblogs.com/it-tsz/p/8726797.html

时间: 2024-10-12 11:41:11

Python 扩展技术总结(转)的相关文章

python扩展实现方法--python与c混和编程

Reference: http://www.cnblogs.com/btchenguang/archive/2012/09/04/2670849.html python 头文件在的位置:/usr/include/python2.7                                  /usr/local/include/python2.7 前言(更新:更方便易用的方式在http://www.swig.org/tutorial.html) 大部分的Python的扩展都是用C语言写的,

如何自学Python爬虫技术

作为程序员或者软件测试员们的一员,置信大家一定都听说过python语言. Python语言这两年是越来越火了,它渐渐崛起也是有缘由的. 比如市场需求.入门简单易学.支持多种语言--当然这些都是很官方的. 说白了,就是 写个web服务,可以用python: 写个服务器脚本,可以用python: 写个桌面客户端,可以用python: 做机器学习数据挖掘,可以用python: 写测试工具自动化脚本依旧可以用python-- Python语言是免费支持的! 既然那么好,如何利用python进行有意义的行

css的扩展技术

CSS的扩展技术 (在原来的CSS语言的基础上扩展了js,可以在里面写js ) 一.less 定义: @color:red; //定义颜色 @body-color:blue; @div-color:yellow; 引用: body{ height:500px; border:1px solid @body-color; //调用了上面的颜色 } 嵌套: div{ height:500px; border:1px solid @div-color;//这里就直接调用了上面的颜色 p{ color:

vs2013在图像处理中的应用(7):开发Python扩展

快乐虾 http://blog.csdn.net/lights_joy/(QQ群:Visual EmbedLinux Tools 375515651) 欢迎转载,但请保留作者信息 很久没有摸图像处理的东西了,近期刚好需要有此需求,希望能够有一个比较好用的开发环境.在学校的时候做图像处理一直用的是matlab,不过现在正好在做VELT的开发,尝试用vs2013+python构造一个适合于自己用的开发环境. 在图像处理中,虽然已经可以用python操纵opencv完成一些算法,但总免不了需要自己写一

window下python 扩展库安装 使用第三方镜像源

0.前言 由于python的官方镜像位于国外,若使用pip或者easy_install安装第三方插件时或许会被限制,甚至连easy_install或pip也无法安装,例如在windows环境下运行ez_setup.py 安装easy_install,可能遇到下图这样尴尬的情况. 图1 运行ez_setup.py失败 遇到这种问题可以”转战“国内的第三方镜像,问题便可迎刃而解.例如豆瓣镜像——http://pypi.douban.com/simple/ 1.安装easy_install 先安装ea

python基础:python扩展包的安装方式

python扩展包有三种安装方式: 1. pip安装方式.python3默认自带pip,无需另外安装:在python2.7版本上默认为easy_install安装工作进行安装,如果需要使用pip安装,需要自行下载安装(可以从http://www.pip-installer.org网站下载). 2. 系统自带的包安装管理工具. 3. 从源代码安装. 使用pip安装:在command命令行中输入:pip install 包名,例如:pip install flask 使用pip安装指定版本:在com

CSS扩展技术-less

在原来的CSS基础上扩展一些编程语言 CSS引用扩展技术时需要编译器编译<编译工具Koala 1.less<比较早期的CSS扩展技术> a.less语法:后缀名<.less> //变量的定义 @color:blue; @body-color:blue; @div-color:blue; @w:100px; @h:100px; body{ height:500px; border:1px solid @body-color; } div{ width:@w; height:@h

监控开发之用python扩展dstat插件自定义实时监控

dstat是一个python开源的实时监控工具,一般是用来做系统性能监控的.咱们这里只是提他的自定义插件开发,用来打造自己的dstat. 有朋友可能还没清楚是啥意思, 咱们查看系统的状体状态有人喜欢用vmstat,也有人喜欢用dstat.相比来说dstat的功能模块更全一点是,这里还只是说查看系统性能方面的 !   如果想一边查看,系统的各方面性能指标,还想看你应用的一些个负载相关,比如某个程序的负载,mongodb的锁lock百分比,mysql连接数...   懂了吧 ! 下面是dstat的插

CSS 扩展技术

CSS扩展技术有两种: 1:LESS 2:SCSS/SASS less作为CSS的一种扩展,LESSCSS不仅向下兼容CSS的语法,而且连新增的特性也是使用CSS的语法.这样的设计使得学习LESS很轻松,而且你可以在任何时候回退到CSS. 申明变量的方法: @width:100px; @backgroundColor:blue; 其变量是“按需加载”(lazy loaded)的,因此不必强制在使用之前声明. 在 LESS 中可以定义一些通用的属性集为一个 class,然后在另一个 class 中