1. python和cython是什麼關系
Python和c的混血Cython作為一個Python的編譯器,在科學計算方面很流行,用於提高Python的速度,通過OpenMPI庫還可以進行吧並行計算。
2. 如何編譯c文件中調用 cython
以下總結出幾種在Python 中調用 C/C++ 代碼的方法
--------------------------------------------------------------------
發現做便捷的是使用popen
from os import popen
popen('/home/pengyan/Downloads/VIC/sanxia/vicNl -g /home/pengyan/Downloads/VIC/sanxia/xings_global')
popen('/home/pengyan/Downloads/VIC/sanxia/rout /home/pengyan/Downloads/VIC/sanxia/xings_rout')
?? 目前還不會用python 切換文件目錄
可以採用絕對路徑,但是好像絕對路徑時,計算速度變慢
-------------------------------------------------------------------
使用ctypes 模塊調用 C 動態庫
從Python2.5 開始, Python 開始提供 ctypes 模塊來提供對 C 語言編譯的動態庫文件的調用。注意, 這里特指C 的動態庫 ,用C++ 編譯的動態庫 ctypes 雖然能夠載入,但調用時的函數名已經由於 C++ 的重載特性被加以修改,難以調用。 使用 ctypes 調用 C 動態庫的好處在於不用進行額外的開發,可以直接使用編譯好的動態庫。 ctypes 提供了完整的 C 類型封裝,也支持自定義類型,大大減少在調用過程中的工作量。 ctypes 的使用很簡單,只需熟悉 python 封裝與 C 中的對應關系即可。以下用一個簡單的例子來說明:
from ctypes import * #導入ctypes模塊
libc = cdll.LoadLibrary("libc.so.6") #載入libc動態庫
str = c_char_p(' Hello World! ') #使用char *在ctypes中的對應封裝c_char_p,相當於char* str=」Hello World!」
libc.printf(「yell: %s\n」, str ) #調用printf函數
ctypes的功能當然遠不止這些,有興趣的同學可以參考這里 http://docs.python.org/library/ctypes.html
使用Python 的擴展( Extending )機制
ctypes很方便地可以調用 C 的動態庫,但是對 C++ 編譯的動態庫,調用起來很困難。這種情況利用 Python 的 Extending 機制就可以解決。 Python 提供了一套完整的框架來使用 C/C++ 編寫擴展庫,可以很靈活的開發 C++ 擴展模塊。這種方法的缺點是工作量比較大,需要為每一個方法編寫介面,這里不做詳細介紹,可以參考: http://docs.python.org/extending/extending.html#writing-extensions-in-c
那麼有什麼辦法可以高效的調用C++ 動態庫呢,答案是 SWIG 。
使用SWIG 生成擴展模塊
上面提到了Python 的擴展機制,缺點是工作量比較大,這里介紹一個工具 SWIG 。 SWIG 是一種簡化腳本語言與 C/C++ 介面的開發工具,通過包裝和編譯 C 語言程序來達到與腳本語言通訊目的的工具。它正是基於 Python 的擴展機制,自動生成介面文件,再編譯成可以被 Python 調用的動態庫擴展模塊。
使用SWIG 生成擴展模塊分為以下幾步:
將需要調用的代碼編譯成目標文件(.o) ;
用SWIG 讀取編寫描述文件 (.i) ,生成介面文件 (.cxx) ;
將介面文件編譯為目標文件(.o) ;
將介面文件的目標文件和原代碼段的目標文件一起編譯成動態庫 ;
假設有如下文件
swig_ex.cpp 需要轉換成擴展庫的原始代碼,包含一個int fact(int) 函數
swig_ex.h 原始代碼的頭文件
swig_ex.i SWIG描述文件
swig_ex.i是一個描述文件,有 SWIG 自己的語法,比較簡單,內容如下:
%mole swig_ex
%{
#define SWIG_FILE_WITH_INIT
#include "swig_ex.h"
%}
int fact(int n);
再寫一個Makefile 來把這些文件編譯成動態庫 :
all: swig_ex.o swig_ex_wrap.o _swig_ex.so
swig_ex.o: swig_ex.cpp swig_ex.h #編譯源文件
g++ -fPIC -c swig_ex.cpp
swig_ex_wrap.o: swig_ex.i swig_ex.o #根據 SWIG 描述文件 (.i) 生成介面文件 (.cxx) ,再編譯之
swig -c++ -python swig_ex.i
g++ -O2 -fPIC -c swig_ex_wrap.cxx -I/home/work/linyi/autoframe/tool/python/include/python2.6/
_swig_ex.so: swig_ex_wrap.o #將目標文件打包成動態庫
g++ -shared swig_ex.o swig_ex_wrap.o -o _swig_ex.so
.PHONY: clean
clean:
rm -rf swig_ex_wrap.* swig_ex.py _swig_ex.so
編譯好以後會有一個so 和 py 文件,寫一個 setup.py 把他們安裝到 python 目錄就可以和其他模塊一樣被 python 調用了:
Import swig_ex
swig_ex.fact(10)
參考文檔地址:http://www.swig.org/Doc1.3/SWIGDocumentation.html
原始但有效的方法
除了上面這些方法,在Python 中借用 C/C++ 代碼最原始有效的方法就是將代碼編譯成可執行程序,從 Python 里用 Popen 方法來調用獲取輸出。這種方法簡單有效,缺點是不夠靈活,有比較大的局限性,不過在很多情況下也已經足夠了。
pipe = os.popen('./tool –a %s –b %s' % (「hello」, 「world」))
re = pipe.read()
其他方法
以上這些方法基本上已經能滿足Python 調用 C/C++ 的需求了,此外還有一些方法,例如使用 Boost.Python ,使用 Pyrex ,這些方法都能提供 Python 與 C/C++ 的交互。
總結
在Python 中引用 C/C++ 模塊的方法較多,根據需要從中選擇恰當的方法可以減少很多工作量。
在Python 中引用 C/C++ 模塊彌補了 Python 腳本測試框架的很多不足,在提高代碼復用率的同時,模塊的性能也大大提高。
3. python怎麼使用cython
1. Cython是什麼?
它是一個用來快速生成Python擴展模塊(extention mole)的工具
語法是Python和c的混血
Cython作為一個Python的編譯器,在科學計算方面很流行,用於提高Python的速度,通過OpenMPI庫還可以進行吧並行計算。
2. Cython安裝(Windows)
我的環境是win7 x64, python27, vs2010
安裝的基礎是有一個c編譯器(這里以vs2010為例)
從http://cython.org下載安裝包,解壓到一目錄,進入該目錄,在cmd命令行中執行
python setup.py install
註:執行過程可能遇到問題:Windows下pip安裝包報錯:Microsoft Visual C++ 9.0 is required Unable to find vcvarsall.bat
解決方案:下載Microsoft Visual C++ Compiler for Python 2.7,點擊直接安裝即可。
3. 例子
例3.1:入門
創建hello.pyx,內容如下
def say_hello():
print "Hello World!"
創建setup.py,內容如下
from distutils.core import setup
from Cython.Build import cythonize
setup(name = 'Hello world app',
ext_moles = cythonize("hello.pyx"))
編譯Cython代碼
step1: 把.pyx文件被Cython便以為.c文件
step2: 把.c文件編譯為可導入的使用模塊.so(Windows下為.pyd)文件
1
2
python setup.py build
python setup.py install
註:可能出現問題:Unable to find vcvarsall.bat
原因:Python 2.7 會搜索 Visual Studio 2008.如果你電腦上沒有這個版本的話就會報錯。
如果裝的是vs2010,那麼在cmd命令行中執行
1
SET VS90COMNTOOLS=%VS100COMNTOOLS%
如果裝的是vs2010,那麼在cmd命令行中執行
1
SET VS90COMNTOOLS=%VS110COMNTOOLS%
執行
1
2
3
>>> import hello
>>> hello.say_hello()
Hello World!例3.2 通過靜態類型提高速度
在Cython中可以通過標記靜態類型來提高速度,凡是標記為靜態類型的部分都會將動態語言類型變為簡單的c代碼,從而提速。
但是如果濫用靜態類型,會降低可讀性,甚至因類型設置不當導致錯誤類型檢查造成速度降低。
例3.2.1 靜態類型變數
Python原生態代碼
compute.pyx
def f(x):
return x ** 2 - x
def integrate_f(a, b, N):
s = 0
dx = (b - a) / N
for i in range(N):
x += f(a + i * dx)
return s * dx
setup.py
from distutils.core import setup
from Cython.Build import cythonize
setup(
name = 'Hello world app',
ext_moles = cythonize("compute.pyx"),
)
test.py
import compute
import time
starttime = time.clock()
compute.integrate_f(3.2, 6.9, 1000000)
endtime = time.clock()
print "read: %f s" %(endtime - starttime)
執行
1
2
3
python setup.py build
python setup.py install
python test.py
結果
1
read: 0.332332 s
使用靜態變數替換後的代碼
compute2.pyx
def f(double x):
return x ** 2 - x
def integrate_f(double a, double b, int N):
cdef int i
cdef double s, dx
s = 0
dx = (b - a) / N
for i in range(N):
s += f(a + i * dx)
return s * d
setup2.py
from distutils.core import setup
from Cython.Build import cythonize
setup(
name = 'Hello world app',
ext_moles = cythonize("compute2.pyx"),
)
test2.py
import compute2
import time
starttime = time.clock()
compute2.integrate_f(3.2, 6.9, 1000000)
endtime = time.clock()
print "read: %f s" %(endtime - starttime)
執行
1
2
3
python setup.py build
python setup.py install
python test.py
結果
1
read: 0.109200s
結論
該測試用例,使用靜態類型速度是不使用靜態類型的3倍。
例3.2.2 靜態類型函數
把compute2.pyx中的函數變為
cdef double f(double x):
return x ** 2 - x
def integrate_f(double a, double b, int N):
cdef int i
cdef double s, dx
s = 0
dx = (b - a) / N
for i in range(N):
s += f(a + i * dx)
return s * dx
結果
1
read: 0.084859 s
結論:比例子3.2.1速度又快了
例3.3 調用C函數
cdef extern from "math.h":
double sin(double)
double cos(double)
cpdef double Sin(double x):
return sin(x)
cpdef double Cos(double x):
return cos(x)
cpdef: 對於Python可使用的函數使用(為了使得在以後的Python程序中調用Sin,Cos函數,用cpdef,而不用cdef)
cdef: 對於C可使用的函數使用
請注意,上面的代碼聲明了 math.h 里的函數,提供給 Cython 使用。C編譯器在編譯時將會看到 math.h 的聲明,但 Cython 不會去分析 math.h 和單獨的定義。
4. python怎麼使用cython
1.找個工具將這個介面API,自動轉換成python版本的就可以了。好象是SWIG和Boost。 這兩個以前看過,偶爾還試過幾次。
2.之所以建議你用自動工具,就是因為python對於C++擴展麻煩些,對於C語言介面可以使用ctypes和cython簡單解決。
5. 為什麼python cython
與TNonblockingServer模式相比,THsHaServer在完成數據讀取之後,將業務處理過程交由一個線程池來完成,主線程直接返回進行下一次循環操作,效率大大提升!
6. cython和python的區別
cython是用c寫的python實現
Cython是不同的語言,相當於Python再加上些C特性,比如說類型聲明。
7. cython與python的不同有哪些
Cython是Python的一個超集,結合了Python的易用性和原生代碼的速度,可以編譯成C語言,產生的性能提升可以從幾個百分點到幾個數量級,具體取決於手頭的任務。
使用Cython,你可以避開Python的許多原生限制,或者完全超越Python,而無需放棄Python的簡便性和便捷性。
Python代碼可以直接調用C模塊。這些C模塊可以是通用的C庫或專門為Python工作的庫。Cython生成第二種類型的模塊:與Python內部對話的C庫,可以與現有的Python代碼綁定在一起。
Cython代碼在設計上看起來很像Python代碼。如果你給Cython編譯器提供了一個Python程序,它將會按原樣接受它,但是Cython的原生加速器都不會起作用。但是如果你用Cython的特殊語法來修飾Python代碼,那麼Cython就可以用快速的C代替慢的Python對象。
請注意,Cython的方法是漸進的。這意味著開發人員可以從現有的Python應用程序開始,通過對代碼立刻進行更改來加快速度,而不是從頭開始重寫整個應用程序。
這種方法通常與軟體性能問題的性質相吻合。在大多數程序中,絕大多數CPU密集型代碼都集中在一些熱點上,也就是帕累托原則的一個版本,也被稱為「80/20」規則。因此,Python應用程序中的大部分代碼不需要進行性能優化,只需要幾個關鍵部分。你可以逐漸將這些熱點轉換為Cython,從而獲得你最需要的性能提升。程序的其餘部分可以保留在Python中,以方便開發人員。
相關推薦:《Python入門教程》
Cython優勢
除了能夠加速已經編寫的代碼之外,Cython還具有其他幾個優點:
使用外部C庫可以更快
像NumPy這樣的Python軟體包可以在Python界面中打包C庫,使它們易於使用。但是,這些包在Python和C之間來回切換會減慢速度。Cython可以讓你直接與底層庫進行通信,而不需要Python(也支持C ++庫)。
可以同時使用C和Python內存管理
如果你使用Python對象,它們就像在普通的Python中一樣被內存管理和垃圾收集。但是如果你想創建和管理自己的C級結構,並使用malloc/free來處理它們,你可以這樣做,只記得自己清理一下。
可以根據需要選擇安全性或速度
Cython通過decorator 和編譯器指令(例如@boundscheck(False))自動執行對C中彈出的常見問題的運行時檢查,例如對數組的超出邊界訪問。因此,由Cython生成的C代碼默認比手動C代碼安全得多。
如果確信在運行時不需要這些檢查,則可以在整個模塊上或僅在選擇功能上禁用它們以獲得額外的編譯速度。
Cython還允許本地訪問使用「緩沖協議」的Python結構,以直接訪問存儲在內存中的數據(無需中間復制)。Cython的「記憶視圖」可以高速地在這些結構上進行工作,並且具有適合任務的安全級別。
Cython C代碼可以從釋放GIL中受益
Python的全局解釋器鎖(Global Interpreter Lock,GIL)同步解釋器中的線程,保護對Python對象的訪問並管理資源的爭用。但GIL被廣泛批評為Python性能的絆腳石,特別是在多核系統上。
如果有一段代碼不會引用Python對象並執行長時間運行,那麼可以使用nogil:指令將其標記為允許它在沒有GIL的情況下運行。這使得Python中間人可以做其他事情,並允許Cython代碼使用多個內核(附加工作)。
Cython可以使用Python類型的提示語法
Python有一個類型提示語法,主要由linters和代碼檢查器使用,而不是CPython解釋器。 Cython有它自己的代碼裝飾的自定義語法,但是最近修改了Cython,你可以使用Python類型提示語法為Cython提供類型提示。
Cython限制
請記住,Cython不是一個魔術棒。它不會自動將每一個poky Python代碼變成極速的C代碼。為了充分利用Cython,你必須明智地使用它,並理解它的局限性:
常規Python代碼的加速很少
當Cython遇到Python代碼時,它不能完全翻譯成C語言,它將這些代碼轉換成一系列對Python內部的C調用。這相當於將Python的解釋器從執行循環中提取出來,這使得代碼默認加速了15%到20%。請注意,這是最好的情況。在某些情況下,可能看不到性能改善,甚至性能下降。
原生Python數據結構有一點加速
Python提供了大量的數據結構 - 字元串,列表,元組,字典等等。它們對於開發者來說非常方便,而且他們自帶了自動內存管理功能,但是他們比純C慢。
Cython讓你繼續使用所有的Python數據結構,盡管沒有太多的加速。這又是因為Cython只是在Python運行時調用創建和操作這些對象的C API。因此,Python數據結構的行為與Cython優化的Python代碼大致相同:有時會得到一個提升,但只有一點。
Cython代碼運行速度最快時,「純C」
如果你在C中有一個標有cdef關鍵字的函數,那麼它的所有變數和內聯函數調用都是純C的,所以它的運行速度可以和C一樣快。 但是,如果該函數引用任何Python原生代碼(如Python數據結構或對內部Python API的調用),則該調用將成為性能瓶頸。
幸運的是,Cython提供了一種方法來發現這些瓶頸:一個源代碼報告,一目瞭然地顯示您的Cython應用程序的哪些部分是純C以及哪些部分與Python交互。 對應用程序進行了更好的優化,就會減少與Python的交互。
為Cython應用程序生成的源代碼報告。 白色區域純C;黃色區域顯示與Python內部的交互。一個精心優化的Cython程序將盡可能的黃色。 展開的最後一行顯示了解釋其相應Cython代碼的C代碼。
Cython NumPy
Cython改進了基於C的第三方數字運算庫(如NumPy)的使用。由於Cython代碼編譯為C,它可以直接與這些庫進行交互,並將Python的瓶頸帶出循環。
但是NumPy特別適用於Cython。 Cython對NumPy中的特定結構具有本地支持,並提供對NumPy數組的快速訪問。在傳統的Python腳本中使用的熟悉的NumPy語法可以在Cython中使用。
但是,如果要創建Cython和NumPy之間最接近的綁定,則需要使用Cython的自定義語法進一步修飾代碼。例如,cimport語句允許Cython代碼在編譯時在庫中查看C級構造,以實現最快的綁定。
由於NumPy被廣泛使用,Cython支持NumPy「開箱即用」。如果你安裝了NumPy,你可以在你的代碼中聲明cimport numpy,然後添加進一步的裝飾來使用暴露的函數。
Cython分析和性能
可以通過分析代碼並親眼目睹瓶頸在哪裡獲得最佳性能。Cython為Python的cProfile模塊提供鉤子,因此可以使用Python自己的分析工具來查看Cython代碼的執行情況。無需在工具組之間切換;可以繼續所熟悉和喜愛的Python世界中工作。
它有助於記住所有情況下,Cython不是魔術,仍然適用明智的現實世界的表現實踐。在Python和Cython之間來回穿梭越少,你的應用運行得越快。
例如,如果你有一個你想要在Cython中處理的對象的集合,那麼不要在Python中迭代它,並且在每一步調用一個Cython函數。將整個集合傳遞給你的Cython模塊並在那裡迭代。這種技術經常在管理數據的庫中使用,因此這是在自己的代碼中模擬的好模型。
我們使用Python是因為它為程序員提供了便利,並且能夠快速開發。有時程序員的工作效率是以犧牲性能為代價的。使用Cython,只需要一點點額外的努力就可以給你兩全其美的好處。
8. cython和python可以混合寫嗎
1)Py3.X去除了long類型,現在只有一種整型——int,但它的行為就像2.X版本的long
2)新增了bytes類型,對應於2.X版本的八位串,定義一個bytes字面量的方法如下:
>>> b = b'china'
>>> type(b)
<type 'bytes'>
str對象和bytes對象可以使用.encode() (str -> bytes) or .decode() (bytes -> str)方法相互轉化。
>>> s = b.decode()
>>> s
'china'
>>> b1 = s.encode()
>>> b1
b'china'
9. 如何使用cython編譯擴展
先是安裝Cython。由於我只有Windows,所以就只介紹這個平台。
英文的說明可以看《InstallingOnWindows》,共有2步:
一、安裝MinGW。現在SF已不提供完整安裝版了,只能下載在線安裝版。由於Cython也支持C++,所以我也勾選了g++編譯器。
裝好後把MinGW目錄/bin加入PATH環境變數,並保證gcc --version可以正確執行。
接著去Python目錄\Lib\distutils下添加一個distutils.cfg文件,內容如下:
[build]
compiler = mingw32
實際上這最後一步也可不做,但每次編譯都需要加一個-c參數來指定編譯器。
二、安裝Cython。
我是直接下載exe版本的,直接運行即可。Python 2.4可能還要做些額外處理,我沒有這個版本,沒法測試。
接著就可以來測試了,先來寫個hello world。
hw.py:
def hi():
print "Hello World"
setup.py:
from distutils.core import setup
from distutils.extension import Extension
from Cython.Distutils import build_ext
setup(
cmdclass = {'build_ext': build_ext},
ext_moles = [Extension("hw", ["hw.py"])]
)
然後運行這段代碼進行編譯:
setup.py build_ext --inplace
這就生成了很多文件,其中hw.pyd就是生成的C擴展了。
接著測試一下:
>>> from hw import hi
>>> hi()
Hello World
然後來測試下性能:
csigma.py和pysigma.py:
def sigma(n):
a = 0
for i in xrange(n):
a += i
return a
測試腳本:
from timeit import Timer
print Timer('sigma(10000)','from csigma import sigma').timeit(10000)
print Timer('sigma(10000)','from pysigma import sigma').timeit(10000)
10. cython編譯為可執行文件,目標機器上不用安裝Python環境就可以執行
本來就是腳本語言,要做窗口程序的話用C#,VB,再不用易語言也可以
python,lua之類的這方面都有各種弊端
再看看別人怎麼說的。