前言
ctypes是python的外部函式庫。它提供了c相容的資料型別,並且允許呼叫動態鏈結庫/共享庫中的函式。它可以將這些庫包裝起來給python使用。這個引入c語言的介面可以幫助我們做很多事情,比如需要呼叫c**的來提高效能的一些小型問題。通過它你可以接入windows系統上的 kernel32.dll 和 msvcrt.dll 動態鏈結庫,以及linux系統上的 libc.so.6 庫。當然你也可以使用自己的編譯好的共享庫
我們先來看乙個簡單的例子 我們使用 python 求 1000000 以內素數,重複這個過程10次,並計算執行時間。
import math
from timeit import timeit
def check_prime(x):
values = xrange(2, int(math.sqrt(x)) + 1)
for i in values:
if x % i == 0:
return false
return true
def get_prime(n):
return [x for x in xrange(2, n) if check_prime(x)]
print timeit(stmt='get_prime(1000000)', setup='from __main__ import get_prime',
number=10)
輸出42.8259568214
下面用c語言寫乙個的check_prime函式,然後把它當作共享庫(動態鏈結庫)匯入
#include
#include
int check_prime(int a)
return 1;
}使用以下命令生成 .so (shared object)檔案
gcc -shared -o prime.so -fpic prime.c
import ctypes
import math
from timeit import timeit
check_prime_in_c = ctypes.cdll('./prime.so').check_prime
def check_prime_in_py(x):
values = xrange(2, int(math.sqrt(x)) + 1)
for i in values:
if x % i == 0:
return false
return true
def get_prime_in_c(n):
return [x for x in xrange(2, n) if check_prime_in_c(x)]
def get_prime_in_py(n):
return [x for x in xrange(2, n) if check_prime_in_py(x)]
py_time = timeit(stmt='get_prime_in_py(1000000)', setup='from __main__ import get_prime_in_py',
number=10)
c_time = timeit(stmt='get_prime_in_c(1000000)', setup='from __main__ import get_prime_in_c',
number=10)
print "python version: {} seconds".format(py_time)
print "c verswww.cppcns.comion: {} seconds".format(c_time)
輸出python version: 43.4539749622 seconds
c version: 8.56250786781 seconds
我們可以看到很明顯的效能差距 這裡有更多的方法去判斷乙個數是否是素數
再來看乙個複雜點的例子 快速排序
mylib.c
#include
typedef struct _ra range;
range new_range(int s, int e)
void swap(int *x, int *y)
void quick_sort(int arr, const int len)
if (arr[left] >= arr[range.end])
swap(&arr[left], &arr[range.end]);
else
left++;
r[p++] = new_range(range.start, left - 1);
r[p++] = new_range(left + 1, range.end);
}}gcc -shared -o mylib.so -fpic mylib.c
使用ctypes有乙個麻煩點的地方是原生的c**使用的型別可能跟python不能明確的對應上來。比如這裡什麼是python中的陣列?列表?還是 array 模組中的乙個陣列。所以我們需要進行轉換
test.py
import ctypes
import time
import random
quick_sort = ctypes.cdll('./mylib.so').quick_sort
nums =
for _ in range(100):
r = [random.randrange(1, 100000000) for x in xrange(100000)]
arr = (ctypes.c_int * len(r))(*r)
nums.append((arr, len(r)))
init = time.clock()
for i in range(100):
quick_sort(nums[i][0], nums[i][1])
print "%s" % (time.clock() - init)
輸出1.874907
與python list 的 sort 方法進行對比
import ctypes
import time
import random
quick_sort = ctypes.cdll('./mylib.so').quick_sort
nums =
for _ in range(1程式設計客棧00):
nums.append([random.randrange(1, 100000000) for x in xrange(100000)])
init = time.clock()
for i in range(100):
nums[i].sort()
print "%s" % (time.clock() - init)
輸出2.501257
至於結構體,需要定義乙個類,包含相應的字段和型別
class point(ctypes.structure):
_fields_ = [('x', ctypes.c_double),
('y', ctypes.c_double)]
除了匯入我們自己寫的c語言擴充套件檔案,我們還可以直接匯入系統提供的庫檔案,比如linux下c標準庫的實現 glibc
import time
import random
from ctypes import cdll
libc = cdll.loadlibrary('libc.so.6') # linu系統
# libc = cdll.msvcrt # windows系統
init = time.clock()
randoms = [random.randrange(1, 100) for x in xrange(1000000)]
print "python version: %s seconds" % (time.clock() - init)
init = time.clock()
randoms = [(libc.rawww.cppcns.comnd() % 100) for x in xrange(1000000)]
print "c version : %s seconds" % (time.clock() - init)
輸出python version: 0.850172 seconds
c version : 0.27645 seconds
總結本文標題: 利用ctypes提高python的執行速度
本文位址:
利用pyinstaller打包python3程式
這裡我解壓到了d盤 接著進入win系統的cmd介面,在cmd狀態下進入pyinstaller檔案。然後輸入 最好以管理員身份執行 這裡是在python裡安裝pyinstaller模組 python setup.py install 必須確保你的機器上安裝了pywin32模組,如果沒有請自行安裝。以管...
利用 Ordered 提高查詢效能
消耗在準備利用oracle執行計畫機制提高查詢效能新的sql語句的時間是oracle sql語句執行時間的最重要的組成部分。但是通過理解oracle內部產生執行計畫的機制,你能夠控制oracle花費在評估連線順序的時間數量,並且能在大體上提高查詢效能。準備執行sql語句 當sql語句進入oracle...
如何利用FutureBuilder提高開發效率
常見場景 抽象模式 轉換成程式語言 以上三種現實情況對應 asyncsnapshot 三個狀態 使用 futurebuilder 處理這個場景 這篇文章的主角,futurebuilder 就是為了解決這個問題存在的。它接收乙個 future 請求,和對應以上幾種情況的 widget 即可把資料和介面...