<wbr id="juant"></wbr>
  • <wbr id="juant"></wbr>
    更多課程 選擇中心


    Python培訓

    400-111-8989

    Python和C/C++交互有幾種方法?

    • 發布:Python培訓
    • 來源:Python常見問題
    • 時間:2017-07-12 16:27

    Python編程語言

    Python 是一種面向對象、解釋型計算機程序設計語言,由Guido van Rossum于1989年底發明,第一個公開發行版發行于1991年。Python語法簡潔而清晰,具有豐富和強大的類庫。它常被昵稱為膠水語言,它能夠把用其他語言制作的各種模塊(尤其是C/C++)很輕松地聯結在一起。

    這篇文章主要給大家總結介紹了Python和C/C++交互的幾種方法,文中介紹的非常詳細,對大家具有一定的參考學習價值,需要的朋友們下面來一起看看吧。

    前言

    python作為一門腳本語言,其好處是語法簡單,很多東西都已經封裝好了,直接拿過來用就行,所以實現同樣一個功能,用Python寫要比用C/C++代碼量會少得多。但是優點也必然也伴隨著缺點(這是肯定的,不然還要其他語言干嘛),python最被人詬病的一個地方可能就是其運行速度了。這這是大部分腳本語言共同面對的問題,因為沒有編譯過程,直接逐行執行,所以要慢了一大截。所以在一些對速度要求很高的場合,一般都是使用C/C++這種編譯型語言來寫。但是很多時候,我們既想使用python的簡介優美,又不想損失太多的性能,這個時候有沒有辦法將python與C/C++結合到一起呢?這樣在性能與速度要求不高的地方,可以用pyhton寫,而關鍵的運算部分用C/C++寫,這樣就太好了。python在做科學計算或者數據分析時,這是一個非常普遍的需求。要想實現這個功能,python為我們提供了不止一種解決辦法。

    下面我就逐一給大家介紹。

    一、Cython 混合python與C

    官方網址:http://docs.cython.org/en/latest/src/quickstart/overview.html。首先來看看cython的官方介紹吧。

    [Cython] is a programming language that makes writing C extensions for the Python language as easy as Python itself. It aims to become a superset of the [Python]language which gives it high-level,  object-oriented, functional, and dynamic programming. Its main feature on top of these is support for optional static type declarations as part of the language. The source code gets translated into optimized C/C++ code and compiled as Python extension modules. This allows for both very fast program execution and tight integration with external C libraries, while keeping up the high programmer productivity for which the Python language is well known.

    簡單來說,cython就是一個內置了c數據類型的python,它是一個python的超集,兼容幾乎所有的純python代碼,但是又可以使用c的數據類型。這樣就可以同時使用c庫,又不失python的優雅。

    好了,不講太多廢話,直接來看cython如何使用吧。這里的介紹大部分來自官網,由于cython涉及到的東西還比較多,所以這里只是簡單的入門介紹,詳細的信息請移步英文官網。

    使用cython有兩種方式:第一個是編譯生成Python擴展文件(有點類似于dll,即動態鏈接庫),可以直接import使用。第二個是使用jupyter notebook或sage notebook 內聯 cython代碼。

    先看第一種。還是舉最經典的hello world的例子吧。新建一個hello.pyx文件,定義一個hello函數如下:

    def hello(name): print("Hello %s."% name)

    然后,我們來寫一個setup.py 文件(寫python擴展幾乎都要寫setup.py文件,我之前也簡單介紹過怎么寫)如下:

    #!/usr/bin/env python # -*- coding: utf-8-*- # @Time :2017/5/89:09# @Author : Lyrichu # @Email :919987476@qq.com # @File : setup.py''' @Description: setup.py for hello.pyx '''from Cython.Build import cythonize from distutils.core import setup # 編寫setup函數 setup( name ="Hello", ext_modules = cythonize("hello.pyx") )

    其中 ext_modules 里面寫你要 編譯的.pyx文件名字。OK,所有工作都完成了。接下來,進入cmd,切換到setup.py 所在的文件,然后執行命令: python setup.py build_ext --inplace就會編譯生成一個build 文件夾以及一個.pyd文件了,這個pyd文件就是python的動態擴展庫,--inplace 的意思是在當前文件目錄下生成.pyd文件,不加這一句就會在build文件夾中生成。

    可以看出,除了生成了一個pyd文件之外,還生成了一個.c文件。test.py是我們用來測試的文件,在里面寫如下內容:

    from hello import hello hello("lyric")

    從hello 模塊導入 hello函數,然后直接調用就可以了。結果輸出 Hello lyric.

    再來看如何 在 jupyter notebook中使用cython。如果你裝過ipython,一個升級版的python交互式環境,你應該聽過 ipyhton notebook的大名,現在它升級了,改名叫jupyter notebook 了。簡單來說,這個就是一個可以在網頁環境下交互式使用python的工具,不僅可以實時看到計算結果,還可以直接展示表格,圖片等,功能還是非常強大的。首先你得安裝jupyter notebook.我印象中安裝了ipython之后應該就會帶了jupyter了。如果沒有,可以直接 pip install jupyter .然后輸入命令 jupyter notebook就會在瀏覽器中打開jupyter了。

    點擊右上角的new按鈕,可以選擇新建一個文本文件或者文件夾,markdown或者python文件,這里我們選擇新建一個pyhton 文件,然后就會轉到一個新的窗口了,如下圖3:

    In[]:和ipython一樣,就代表著我們要輸入代碼的地方,輸入代碼之后,點擊向右的三角形符號,就會執行代碼了。

    首先輸入 %load_ext cython,然后執行,%開頭的語句是jupyter的魔法命令,%是行命令,%%是單元命令,具體不多說,有空給大家專門介紹一下notebook的使用。

    接下來輸入:

    %%cython cdef int a =0foriinrange(10):  a += i print(a)

    %%cython 表明將cython內嵌到jupyter,cdef 是cython的關鍵字,用于定義c類型,這里將a定義為c中的int類型,并且初始化為0.

    然后后面的循環就是累加0到9的意思,最后輸出45.

    另外,我們如果想分析代碼 的執行情況,可以輸入 %%cython --annotate命令,這樣就可以輸出結果的同時,也輸出 詳細的代碼執行情況報告了。

    jupyter notebook 可以內嵌cython,不用我們手寫setup.py 文件,省去了編譯的過程,方便了cython的使用,所以不是正式做項目,只是寫一寫小東西用jupyter+cython還是非常方便的。

    前面提到了 cdef,再舉一個稍微復雜點的例子吧。還是引用官網的例子,寫一個算積分的函數.新建 integrate.pyx 文件,寫入如下內容:

    #!/usr/bin/env python # -*- coding: utf-8-*- # @Time :2017/5/89:26# @Author : Lyrichu # @Email :919987476@qq.com # @File : integrate.py''' @Description: 積分運算,使用 cython cdef 關鍵字 '''def f(double x):returnx**2- x def integrate_f(double a,double b,int N): cdef int i cdef double s,dx s =0dx = (b-a)/Nforiinrange(N):  s += f(a + i*dx)*dxreturns # 返回定積分

    這段代碼應該也是比較好理解的,f()函數是被積函數,a,b是積分的上下限,N是分割小矩形的個數,注意這里將 變量i,s,dx全部都用cdef 聲明為c類型了,一般來說,在需要密集計算的地方比如循環或者復雜運算,可以將對應的變量聲明為c類型,可以加快運行速度。

    然后和上面一樣編寫 setup.py ,就是把 pyx的文件名改一下,代碼我就不貼了。然后python setup.py build_ext --inplace執行。得到pyd文件,編寫測試文件test.py如下:

    #!/usr/bin/env python # -*- coding: utf-8-*- # @Time :2017/5/89:35# @Author : Lyrichu # @Email :919987476@qq.com # @File : test.py''' @Description: 測試使用cython 混合c與python的integrate 函數與純python寫的integrate函數速度上的差異 '''from integrate import integrate_f import time a =1# 積分區間下界 b =2# 積分區間上界 N =10000# 劃分區間個數 # 使用純python代碼寫的integrate函數 def py_f(x):returnx**2- x def py_integrate_f(a,b,N): dx = (b-a)/N s =0foriinrange(N):  s += py_f(a + i*dx)*dxreturns start_time1 = time.time() integrate_f_res = integrate_f(a,b,N) print("integrate_f_res = %s"% integrate_f_res) end_time1 = time.time() print(u"cython 版本計算耗時:%.8f"% (end_time1 - start_time1)) start_time2 = time.time() py_integrate_f_res = py_integrate_f(a,b,N) print("py_integrate_f_res = %s"% py_integrate_f_res) end_time2 = time.time() print(u"python 版本計算耗時:%.8f"% (end_time2 - start_time2))

    上面的代碼,我們重新使用python寫了一個積分函數py_integrate_f,與pyd中的integrate_f 函數進行運算對比。

    可以看出,使用了cython的版本比純Python的版本大概快了4、5倍的樣子,而這僅僅是將幾個變量改為c類型的結果,可見,cython確實可以方便地對python與c進行混合,獲得速度上的提升,又不失去Python的簡潔優美。

    最后再來說下cython 如何調用c libraries. C 語言 stdlib 庫有一個 atoi函數,可以將字符串轉化為整數,math庫有一個sin函數,我們就以這兩個函數為例。新建 calling_c.pyx 文件,文件內容如下:

    from libc.stdlib cimport atoi from libc.math cimport sin def parse_char_to_int(char * s): assert s is not NULL,"byte string value is NULL"returnatoi(s) def f_sin_squared(double x):returnsin(x*x)

    前兩行導入了C語言中的函數,然后我們自定義了兩個函數,parse_char_to_int 可以將字符串轉換為整數,f_sin_squared 計算 x平方的sin函數值。寫 setup.py 文件,和之前差不多,但是要注意的是,在unix系統下,math庫默認是不鏈接的,所以需要指明其位置,那么在unix系統下,setup.py 文件的內容就需要增加Extension 一項,如下:

    from distutils.core import setup from distutils.extension import Extension from Cython.Build import cythonize ext_modules=[ Extension("calling_c",    sources=["calling_c.pyx"],    libraries=["m"] # Unix-like specific ) ] setup( name ="Calling_c", ext_modules = cythonize(ext_modules) )

    然后直接編即可。test.py文件如下:

    #!/usr/bin/env python # -*- coding: utf-8-*- # @Time :2017/5/812:21# @Author : Lyrichu # @Email :919987476@qq.com # @File : test.py''' @Description: test file '''from calling_c import f_sin_squared,parse_char_to_int str ="012"str_b = bytes(str,encoding='utf-8') = parse_char_to_int(str_b) print("n = %d"%n) from math import pi,sqrt x = sqrt(pi/2) res = f_sin_squared(x) print("sin(pi/2)=%f"% res)

    需要注意的是,Python字符串不能直接傳入 parse_char_to_int函數,需要將其轉換為 bytes 類型再傳入。運行結果為:

    =12sin(pi/2)=1.000000

    如果不想通過libc導入c語言模塊,cython也允許我們自己聲明c函數原型來導入,一個例子如下:

    # 自己聲明c函數原型 cdef extern from"math.h": cpdef double cos(double x) def f_cos(double x):returncos(x)

    使用了 extern 關鍵字。

    每次都編寫setup.py 文件,然后編譯,略顯麻煩。cython還提供了一種更簡單的方法:pyximport。通過導入pyximport(安裝cython時會自動安裝),在沒有引入額外的c庫的情況下,可以直接調用pyx中的函數,更為直接與方便。以前面的hello 模塊為例,編寫好hello.py文件之后,編寫一個pyximport_test.py 文件,文件內容如下:

    import pyximport pyximport.install() import hello hello.hello("lyric")

    直接運行就會發現,確實可以正確導入hello模塊。

    cython的更多內容,請大家自行訪問官網查看。

    其他python與c/c++ 混合編程的方式主要還有 使用 ctypes,cffi模塊以及swig。

    預約申請免費試聽課

    填寫下面表單即可預約申請免費試聽!怕錢不夠?可就業掙錢后再付學費! 怕學不會?助教全程陪讀,隨時解惑!擔心就業?一地學習,可全國推薦就業!

    上一篇:如何理解 Python 的異步編程?
    下一篇:iOS程序員如何使用Python寫網路爬蟲

    Python培訓班線上線下哪種靠譜

    python線上培訓班學費一般多少

    Python線下培訓班有哪些

    一篇文章帶你了解python和c語言的區別

    • 掃碼領取資料

      回復關鍵字:視頻資料

      免費領取 達內課程視頻學習資料

    • 視頻學習QQ群

      添加QQ群:1143617948

      免費領取達內課程視頻學習資料

    Copyright ? 2021 Tedu.cn All Rights Reserved 京ICP備08000853號-56 京公網安備 11010802029508號 達內時代科技集團有限公司 版權所有

    選擇城市和中心
    黑龍江省

    吉林省

    河北省

    湖南省

    貴州省

    云南省

    廣西省

    海南省

    天天日天天射天天干天天伊|奇米电影|奇米网_奇米首页|奇米首页 百度 好搜 搜狗
    <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <文本链> <文本链> <文本链> <文本链> <文本链> <文本链>