说起Python,首先想到的他是一种“胶水语言”。作为一种合格的胶水语言,比起开发的难易程度或者开发效率来讲,语言的适应性和可扩充性同样很重要。python的一大特色是有许多方便灵活的扩展模块。
对于上次我们曾经说过ctypes的方式可能对于已经存在的lib库,这对于已经存在的C libs或者有C程序员参与的情况下是很方便的,但对于很多团队来说,合格的C程序员始终是个缺口。这次我们就说说针对单独的一个模块通过Python的一个扩展Cython进行C重构,从而达到尽可能减少工作量,从而达到最便捷的C重构。
在此之前,安装cython和python-dev(需要Python.h文件参与)
apt-get install python python-dev
python原文件,这次选择的是“费波拉契数列”的计算:
fib.py
def fib(i): a = 0 b = 1 while i > 0: i -= 1 a, b = b, a+b return True
import time from fib import fib startTime = time.time() for i in xrange(1,10): fib(10**6) print time.time() - startTime
执行 python startTest.py得到的运行时间是130.857528925,两分多钟。
准备编译脚本,虽然违背了没有coding,但请相信,代码真的很少
build.py
from distutils.core import setup from distutils.extension import Extension from Cython.Distutils import build_ext setup( cmdclass = {'build_ext': build_ext}, ext_modules = [Extension("fib", ["fib.py"])] )
开始编译:
root@Vhost2:~/testCython# python build.py build_ext --inplace running build_ext cythoning fib.py to fib.c building 'fib' extension creating build creating build/temp.linux-x86_64-2.7 gcc -pthread -fno-strict-aliasing -DNDEBUG -g -fwrapv -O2 -Wall -Wstrict-prototypes -fPIC -I/usr/include/python2.7 -c fib.c -o build/temp.linux-x86_64-2.7/fib.o gcc -pthread -shared -Wl,-O1 -Wl,-Bsymbolic-functions -Wl,-Bsymbolic-functions build/temp.linux-x86_64-2.7/fib.o -o /root/testCython/fib.so
当前目录下应该多出来一个fib.c和fib.so,不要怀疑,.c的那个就是C的源码,而.so则是基于c 的python 扩展。如果你有实力可以在.c文件上进行人肉优化,我想效率也远高于从0开始。其中比较好的一点是,C源码中,python的源码会作为注释添加其中,看起来也很方便。
本文主要介绍的是cython,对于生成出来C代码的优劣不在讨论中,有兴趣欢迎私下交流。
开始新的测试:
删除原来的py库,mv fib.py fib.py.bak && rm -f *.pyc
python startTest.py
得出结果105.579359305,汗!没有想象中的那么突飞猛进。通过cProfile的导出,没有看出什么名堂。
事实上查看了C源码,发觉事实上大量的代码实现的仍旧是Python的逻辑,而Python的效率跟C绝对不是一个等级。这当然存在更加有优势的优化方式,但已经脱离了“快速实现”的本质,本文不再介绍。
考虑到“费波拉契数列”是python实现的经典例子,我重新改动了代码。(方便测试,连函数名都没动,容易误导)
fib.py
def fib(i): a = 0 while i > 0: a += i i -= 1 return a
6.1317088604 : 4.3963329792算是比较显著了吧。
对于编译后的脚本来说,个人觉得性能的提升只是一方面的优势。特别是一些对安全性有要求的应用中,编译后的代码隐蔽性较好,在生产环境中即便别人获得了你的服务器权限,也很难反拆你的算法,避免了很多麻烦。
需要注意的是,对于yield方式实现的迭代器,cython无法完成编译,只能重新修改代码,但对于大多数的代码来说,cython几乎是平滑的。而且你甚至可以写一个全自动的部署脚本,上线后自动完成编译。
转载请注明:爱开源 » Cython快速实现Python的C重构