眾所周知,Python語言是非常簡單易用的,但是python程序在運行速度上還是有一些缺陷。於是,Cython就應運而生了,Cython作為Python的C擴展,保留了Python的語法特點,集成C語言的參數類型指定等特點,從而加快Python代碼的運行速度。本文章就Cython的入門給出一個Demo,供大家參考(以下所涉及文件均在同一目錄下,Python環境為Python3)。
首先,當然是配置Cython的運行環境了,在當前的python環境下,需要有pip工具,沒有的話建議你安裝一個,https://pypi.org/project/pip/。擁有pip工具后,只需要運行如下命令即可搭建好Cython的運行環境了:
pip install cython
接下來,寫一個名為python_evan.py的Python代碼:
import math def my_evan(a ,b): x = math.pi/180.0 c = math.sin(a*x) + math.cos(b*x) r = math.sin(c*a) + math.cos(c*b) return r
然后,為上面的Python代碼寫一個與其對應的名為cython_evan.pyx的Cython代碼:
cimport cython cdef extern from "math.h": float cosf(float theta) float sinf(float theta) cdef float _my_evan(float a,float b): cdef float pi = 3.14159265 cdef float x = pi/180.0 cdef float c = sinf(a*x) + cosf(b*x) cdef float r = sinf(c*a) + cosf(c*b) return r def my_evan(float a,float b): cdef float x = _my_evan(a, b) return x
基本概念:
- Cython程序的擴展名是.pyx
- cimport是Cython中用來引用.pxd文件的命令
- Cython的函數使用cdef定義,並且它可以給所有參數以及返回值指定類型
注意這里使用cdef extern 的方式使用從指定頭文件聲明函數(在此就是使用C標准庫的math.h,而非Python庫中math)。
此時,需要使用如下命令對上面的Cython文件進行編譯,編譯過程會調用Python或C\C++相關函數,編輯完成后會生成名為cython_evan.c文件。
cython cython_evan.pyx
如果運行以上代碼出錯,請查看當前系統中是否安裝C或C++。
以上步驟完成后,需要寫一個名為setup.py的文件來生成動態庫以供Python進行調用,setup.py文件示例如下:
# setup.py # python setup.py build_ext --inplace from distutils.core import setup, Extension from Cython.Build import cythonize import numpy setup(ext_modules = cythonize(Extension( 'cython_evan', sources=['cython_evan.pyx'], language='c', include_dirs=[numpy.get_include()], library_dirs=[], libraries=[], extra_compile_args=[], extra_link_args=[] )))
參數說明:
- ‘cython_evan’ 是我們要生成的動態鏈接庫的名字
- sources 里面可以包含 .pyx 文件,以及后面如果我們要調用 C/C++ 程序的話,還可以往里面加 .c / .cpp 文件
- language 其實默認就是 c,如果要用 C++,改成 c++
- include_dirs 這個就是傳給 gcc 的 -I 參數(numpy.get_include()其實這個只是示例,本程序不需要)
- library_dirs 這個就是傳給 gcc 的 -L 參數
- libraries 這個就是傳給 gcc 的 -l 參數
- extra_compile_args 就是傳給 gcc 的額外的編譯參數,比方說你可以傳一個 -std=c++11
- extra_link_args 就是傳給 gcc 的額外的鏈接參數(也就是生成動態鏈接庫的時候用的)
setup.py文件書寫完成后您可以使用如下命令把Cython程序編譯成動態鏈接庫:
python setup.py build_ext --inplace
當上述命令運行成功后,可以看到當前目錄多出來一個cython_evan.so(動態鏈接庫)和一個build目錄等。
最后,來寫一個Test.py文件對Python和Cython的計算時間進行對比:
import timeit a, b = 30, 60 num = 8000000000 t_python = timeit.Timer("python_evan.my_evan(%f,%f)" % (a,b),"import python_evan") t_cython = timeit.Timer("cython_evan.my_evan(%f,%f)" % (a,b),"import cython_evan") print("python function", t_python.timeit(10000), "sec") print("cython function", t_cython.timeit(10000), "sec")