利用ctypes提高Python的執行速度

來源:本網整理

(因為上次回復引起提者的反感修改如下)1.python的確如樓上所說,更適合快速。但是如果一定要有效率也不是沒有辦法。通常會用C接口。比如象是海量數據處理,我經常用ctypes這個庫,節約內存,同時也提高效率2.python的庫有些是C語言寫的,也優化過,其實速度并不是想象的那么慢。也就比JAVA慢一點吧。我曾經對比過,同樣的計算,優化過的python程序比C語言都要快10倍3.python語言里整型也是對象。通常不會用它直接做大型數組。python在科學計算里是很受歡迎的。方便,開發速度快,其實效率也還是很快的。曾經用python做過一個海量數據分析的分布式數據分析軟件。感覺還是很好的。這套系統運行在一組只有2G-4G內存的老的服務器上。那些服務器的計算速度連我的奔騰CPU的筆記本都比不上。不過依然可以處理幾千萬的用戶數據www.anxorj.tw防采集請勿采集本網。

s">

利用ctypes提高Python的執行速度

投稿:daisy 字體:[增加 減小] 類型:轉載 時間:2016-09-09 我要評論 這篇文章給大家介紹了如何利用ctypes提高Python的執行速度,對大家學習使用python具有一定的參考借鑒價值。有需要的朋友們一起來看看吧。 ">

前言

ctypes是Python的外部函數庫。它提供了C兼容的數據類型,并且允許調用動態鏈接庫/共享庫中的函數。它可以將這些庫包裝起來給Python使用。這個引入C語言的接口可以幫助我們做很多事情,比如需要調用C代碼的來提高性能的一些小型問題。通過它你可以接入Windows系統上的 kernel32.dll 和 msvcrt.dll 動態鏈接庫,以及Linux系統上的 libc.so.6 庫。當然你也可以使用自己的編譯好的共享庫

1.ipython+ctypes:調試/測試LinuxAPI的交互式運行環境ipython是最好的REPL。ㄎ蚁矚gPython,至少有30%的好感來自ipython)REPL的好處不言自明,在開發和調試時能大大的提高效率。尤其是需要對

我們先來看一個簡單的例子 我們使用 Python 求 1000000 以內素數,重復這個過程10次,并計算運行時間。

res=ctypes.pythonapi.PyThreadState_SetAsyncExc(tid,ctypes.py_object(exctype)) if res=0: raise ValueError(\"invalid thread id\") elif res!1: ctypes.pythonapi.PyThreadState_SetAsyncExc(tid,None)

import mathfrom timeit import timeitdef check_prime(x): values = xrange(2, int(math.sqrt(x)) + 1) for i in values: if x % i == 0: return False return Truedef 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)

File\"C:\\Python27\\lib\\ctypes\\_init_.py\",line 365,in_init_ self._handle=_dlopen(self._name,mode) WindowsError:[Error 126] 在使用簡單的谷歌搜索大法之后,得知: 導致這樣的問題有兩個最主要的原因

輸出

直接import libxml2就可以導入libxml2庫了,然后直接調用里面的方法就行了.我也看過libxml2的文檔,給的定義全是基于C語言的,但是python已經有它的綁定庫了,也就是說,所以里面的函數,在python都可以調用.

42.8259568214

這個問題到電腦去解決吧

下面用C語言寫一個的 check_prime 函數,然后把它當作共享庫(動態鏈接庫)導入

#include <stdio.h>#include <math.h>int check_prime(int a){ int c; for ( c = 2 ; c <= sqrt(a) ; c++ ) { if ( a%c == 0 ) return 0; } return 1;}

使用以下命令生成 .so (shared object)文件

gcc -shared -o prime.so -fPIC prime.c

import ctypesimport mathfrom timeit import timeitcheck_prime_in_c = ctypes.CDLL('./prime.so').check_primedef check_prime_in_py(x): values = xrange(2, int(math.sqrt(x)) + 1) for i in values: if x % i == 0: return False return Truedef 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 version: {} seconds".format(c_time)

輸出

直接import libxml2就可以導入libxml2庫了,然后直接調用里面的方法就行了.我也看過libxml2的文檔,給的定義全是基于C語言的,但是python已經有它的綁定庫了,也就是說,所以里面的函數,在python都可以調用.

Python version: 43.4539749622 secondsC version: 8.56250786781 seconds

我們可以看到很明顯的性能差距 這里有更多的方法去判斷一個數是否是素數

再來看一個復雜點的例子 快速排序

mylib.c

#include <stdio.h>typedef struct _Range { int start, end;} Range;Range new_Range(int s, int e) { Range r; r.start = s; r.end = e; return r;}void swap(int *x, int *y) { int t = *x; *x = *y; *y = t;}void quick_sort(int arr[], const int len) { if (len <= 0) return; Range r[len]; int p = 0; r[p++] = new_Range(0, len - 1); while (p) { Range range = r[--p]; if (range.start >= range.end) continue; int mid = arr[range.end]; int left = range.start, right = range.end - 1; while (left < right) { while (arr[left] < mid && left < right) left++; while (arr[right] >= mid && left < right) right--; swap(&arr[left], &arr[right]); } 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 ctypesimport timeimport randomquick_sort = ctypes.CDLL('./mylib.so').quick_sortnums = []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 ctypesimport timeimport randomquick_sort = ctypes.CDLL('./mylib.so').quick_sortnums = []for _ in range(100): 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)

輸出

直接import libxml2就可以導入libxml2庫了,然后直接調用里面的方法就行了.我也看過libxml2的文檔,給的定義全是基于C語言的,但是python已經有它的綁定庫了,也就是說,所以里面的函數,在python都可以調用.

2.501257

至于結構體,需要定義一個類,包含相應的字段和類型

class Point(ctypes.Structure): _fields_ = [('x', ctypes.c_double), ('y', ctypes.c_double)]

除了導入我們自己寫的C語言擴展文件,我們還可以直接導入系統提供的庫文件,比如linux下c標準庫的實現 glibc

import timeimport randomfrom ctypes import cdlllibc = cdll.LoadLibrary('libc.so.6') # Linux系統# 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.rand() % 100) for x in xrange(1000000)]print "C version : %s seconds" % (time.clock() - init)

輸出

直接import libxml2就可以導入libxml2庫了,然后直接調用里面的方法就行了.我也看過libxml2的文檔,給的定義全是基于C語言的,但是python已經有它的綁定庫了,也就是說,所以里面的函數,在python都可以調用.

Python version: 0.850172 secondsC version : 0.27645 seconds

總結

以上就是這篇文章的全部內容,希望對大家學習或使用Python能有一定的幫助,如果有疑問大家可以留言交流。

打包python腳本為exe的坎坷經歷,by pyinstaller方法又應驗了那句歌詞.不經歷風雨,怎么見得了彩虹.安裝過程略去不提,僅提示:pip install pyinstaller打包指令粗看包里的文檔,然后開始打包:打開console就用了這個命令:pyinstaller monitor_rt_quotes.py結果就是比預期麻煩的多的多的:干活,硬盤不停地balabala叫,漫長這里記錄一下控制臺顯示的提示信息:官方文檔對上述指令的解釋為:PyInstaller|analyzes myscript.py and:Writes myscript.spec in the same folder as the script.Creates a folder build in the same folder as the script if it does not exist.Writes some log files and working files in the build folder.Creates a folder dist in the same folder as the script if it does not exist.Writes the myscript executable folder in the dist folder.In the dist folder you find the bundled app you distribute to your users.巨長的提示后,得到了exe文件,有18Mb的大小(太龐大了,肥肥肥!但是結果很悲劇:D:\\DB\\fz\\build\\monitor_rt_quotes>monitor_rt_quotes.exe sz000911Error loading Python DLL:D:\\DB\\fz\\build\\monitor_rt_quotes\\python27.dll(error code 126)估計是沒有添加必要的打包選項造成的.繼續努力.不死心!解決問題需要由簡到繁,先從hellowworld.py做起.搞定了.被打包的文件:helloworld.py,人人皆知.打包的命令:pyinstaller-D helloworld.py打包的console提示:見隨后的引述塊打包發布exe時的紀律(注意事項):很簡單的py腳本.Simple is better than complex.應該遵守Python的規則.所以在打包為exe時,應該盡量減少沒有必要的python包的導入.否則吃的太胖可以運行的exe文件位于:dist 目錄下,而不是build目錄下的.運行后的結果:D:\\DB\\fz>pyinstaller-D helloworld.py155 INFO:PyInstaller:3.2.1155 INFO:Python:2.7.11155 INFO:Platform:Windows-XP-5.1.2600-SP3155 INFO:wrote D:\\DB\\fz\\helloworld.spec155 INFO:UPX is not available.155 INFO:Extending PYTHONPATH with paths['D:\\\\DB','D:\\\\DB\\\\fz']155 INFO:checking Analysis155 INFO:Building Analysis because out00-Analysis.toc is non existent155 INFO:Initializing module dependency graph.155 INFO:Initializing module graph hooks.312 INFO:running Analysis out00-Analysis.toc327 INFO:Adding Microsoft.VC90.CRT to dependent assemblies of final executable required by d:\\anaconda2\\python.exe327 INFO:Found C:\\WINDOWS\\WinSxS\\Policies\\x86_policy.9.0.Microsoft.VC90.CRT_1fc8b3b9a1e18e3b_x-ww_b7353f75\\9.0.30729.1.policy327 INFO:Searching for assembly x86_Microsoft.VC90.CRT_1fc8b3b9a1e18e3b_9.0.30729.1_x-ww.327 INFO:Found manifest C:\\WINDOWS\\WinSxS\\Manifests\\x86_Microsoft.VC90.CRT_1fc8b3b9a1e18e3b_9.0.30729.1_x-ww_6f74963e.manifest327 INFO:Searching for file msvcr90.dll327 INFO:Found file C:\\WINDOWS\\WinSxS\\x86_Microsoft.VC90.CRT_1fc8b3b9a1e18e3b_9.0.30729.1_x-ww_6f74963e\\msvcr90.dll327 INFO:Searching for file msvcp90.dll327 INFO:Found file C:\\WINDOWS\\WinSxS\\x86_Microsoft.VC90.CRT_1fc8b3b9a1e18e3b_9.0.30729.1_x-ww_6f74963e\\msvcp90.dll327 INFO:Searching for file msvcm90.dll343 INFO:Found file C:\\WINDOWS\\WinSxS\\x86_Microsoft.VC90.CRT_1fc8b3b9a1e18e3b_9.0.30729.1_x-ww_6f74963e\\msvcm90.dll343 INFO:Found C:\\WINDOWS\\WinSxS\\Policies\\x86_policy.9.0.Microsoft.VC90.CRT_1fc8b3b9a1e18e3b_x-ww_b7353f75\\9.0.30729.1.policy343 INFO:Adding redirect Microsoft.VC90.CRT version(9,0,21022,8)->(9,0,30729,1)484 INFO:Caching module hooks.500 INFO:Analyzing D:\\DB\\fz\\helloworld.py500 INFO:Loading module hooks.500 INFO:Loading module hook"hook-encodings.py".5405 INFO:Loading module hook"hook-httplib.py".5421 INFO:Looking for ctypes DLLs5437 INFO:Analyzing run-time hooks.5452 INFO:Looking for dynamic libraries6155 INFO:Looking for eggs6155 INFO:Using Python library d:\\anaconda2\\python27.dll6171 INFO:Found binding redirects:[BindingRedirect(name=u'Microsoft.VC90.CRT',language=None,arch=u'x86',oldVersion=(9,0,21022,8),newVersion=(9,0,30729,1),publicKeyToken=u'1fc8b3b9a1e18e3b')]6187 INFO:Warnings written to D:\\DB\\fz\\build\\helloworld\\warnhelloworld.txt6280 INFO:checking PYZ6296 INFO:Building PYZ because out00-PYZ.toc is non existent6296 INFO:Building PYZ(ZlibArchive)D:\\DB\\fz\\build\\helloworld\\out00-PYZ.pyz6968 INFO:Building PYZ(ZlibArchive)D:\\DB\\fz\\build\\helloworld\\out00-PYZ.pyz completed successfully.7062 INFO:checking PKG7062 INFO:Building PKG because out00-PKG.toc is non existent7077 INFO:Building PKG(CArchive)out00-PKG.pkg7125 INFO:Building PKG(CArchive)out00-PKG.pkg completed successfully.7140 INFO:Bootloader d:\\anaconda2\\lib\\site-packages\\PyInstaller\\bootloader\\Windows-32bit\\run.exe7140 INFO:checking EXE7155 INFO:Building EXE because out00-EXE.toc is non existent7155 INFO:Building EXE from out00-EXE.toc7171 INFO:Appending archive to EXE D:\\DB\\fz\\build\\helloworld\\helloworld.exe7171 INFO:Building EXE from out00-EXE.toc completed successfully.7187 INFO:checking COLLECT7202 INFO:Building COLLECT because out00-COLLECT.toc is non existent7202 INFO:Building COLLECT out00-COLLECT.toc7218 INFO:Redirecting Microsoft.VC90.CRT version(9,0,21022,8)->(9,0,30729,1)7375 INFO:Redirecting Microsoft.VC90.CRT version(9,0,21022,8)->(9,0,30729,1)7390 INFO:Updating manifest in C:\\Documents and Settings\\Administrator\\Application Data\\pyinstaller\\bincache00_py27_32bit\\python27.dll7405 INFO:Updating resource type 24 name 2 language 10337468 INFO:Redirecting Microsoft.VC90.CRT version(9,0,21022,8)->(9,0,30729,1)7484 INFO:Updating manifest in C:\\Documents and Settings\\Administrator\\Application Data\\pyinstaller\\bincache00_py27_32bit\\unicodedata.pyd7500 INFO:Updating resource type 24 name 2 language 10337546 INFO:Redirecting Microsoft.VC90.CRT version(9,0,21022,8)->(9,0,30729,1)7562 INFO:Updating manifest in C:\\Documents and Settings\\Administrator\\Application Data\\pyinstaller\\bincache00_py27_32bit\\_hashlib.pyd7562 INFO:Updating resource type 24 name 2 language 10337609 INFO:Redirecting Microsoft.VC90.CRT version(9,0,21022,8)->(9,0,30729,1)7625 INFO:Updating manifest in C:\\Documents and Settings\\Administrator\\Application Data\\pyinstaller\\bincache00_py27_32bit\\_ctypes.pyd7640 INFO:Updating resource type 24 name 2 language 10337687 INFO:Redirecting Microsoft.VC90內容來自www.anxorj.tw請勿采集。

免責聲明 - 關于我們 - 聯系我們 - 廣告聯系 - 友情鏈接 - 幫助中心 - 頻道導航
Copyright © 2017 www.anxorj.tw All Rights Reserved
陕西快乐10分下载