利用ctypes提高Python的執行速度

2022-10-04 21:39:41 字數 4207 閱讀 6609

前言

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 即可把資料和介面...