笔记:借助ctypes实现python和C混合编程。
python语法简洁功能强大,但它的缺点就是比较慢。我认为,混合编程的目的就是:把一些需要快速计算的功能用C实现(也可能不是最主要的吧)。
为了探究C到底能提速多少,下文设计了两组对比实验,一组是测试用python实现某个循环所需时间,另一组是测试python调用C库的某个循环所需的时间(并没有测试多次取均值,因为目的仅仅是定性探究)。
python调用C函数也很简单,步骤是:写C函数---生成dll文件----python调用dll---使用C函数。
需要注意: 本文的代码是基于windows的,所以将C程序封装成dll(动态链接库,Dynamic Link Library);如果用linux的话就是so文件了。
笔记包含以下5部分的记录:
1、动态链接库dll
2、用time模块对程序运行计时
3、用VS生成C编写的dll文件
4、在python中使用ctypes调用C函数
5、代码实现python调用C函数与time运行时间分析
第一部分:动态链接库
Windows使用动态链接库的主要目的应该是提供一些可以被程序共享的代码,同样可以达到节约内存的目的。按照我的理解,就比如我写了一个函数,如果有两个程序想要调用它,就需要两个代码备份,这是极其浪费空间了,所以dll文件的目的就是不需要使用两个文件,当然我这种理解不一定对。
第二部分:用time模块对程序进行计时
python内置了time模块用于提供时间相关的操作,这里使用time来计算程序运行的时间。time.clock()会返回当前的CPU时间或者真实时间,所以通过双循环前后分别调用一次,得到的时间差就是双循环进行的时间。
import time
start_time = time.clock()
for i in range(10000):
for j in range(10000):
temp = 10
end_time = time.clock()
print("time:{}".format(end_time-start_time))
得到的时间为:time: 8.31842660000001
第三部分:用VS生成C编写的dll文件
毫无疑问,必须使用VS来编写这个代码了。顺便提一下,有时出现报错“不是有效的32位文件”,就是因为python是64位的,可以设定VS生成64位dll文件。而且,需要设置输出为dll文件!!(右键工程属性)。
C代码就是双层循环,如下:
#include "stdio.h"
__declspec(dllexport) void loop()
{
int i, j;
int temp = 0 ;
for (i = 0; i < 10000; i++) {
for (j = 0; j < 10000; j++) {
temp = 0;
}
}
}
第四部分:在python中使用ctypes调用C函数
python调用C需要导入ctypes这个库,然后使用ctypes.CDLL("xxx.dll")就能导入库了,使用的时候只需要dll.xxx_method()即可(其中xx_method()是C中定义的函数)
import ctypes
dll = ctypes.CDLL("xxx.dll")
dll.xx_method()
第五部分:代码实现python调用C函数与time运行时间分析
首先是使用python实现双层循环的代码:
import time
def loop():
for i in range(10000):
for j in range(10000):
temp = 10
start_time = time.clock()
loop()
end_time = time.clock()
print("time: {}".format(end_time-start_time))
得到的运行时间:time: 2.474646600000142,也就是大概两秒
然后就是python调用第三部分写的C代码了:
import ctypes
import time
dll = ctypes.CDLL("Project2.dll")
start_time = time.clock()
dll.loop()
end_time = time.clock()
print("time: {}".format(end_time-start_time))
得到的时间:time: 0.16221779999978025,大概0.2秒的样子
没错!!!提速不止十倍!!