Python調用C模塊以及性能分析

2021-01-11 TechWeb

一.c,ctypes和python的數據類型的對應關係

ctypes type ctype Python type c_char char 1-character string c_wchar wchar_t 1-character unicode string c_byte char int/long c_ubyte unsigned char int/long c_short short int/long c_ushort unsigned short int/long c_int int int/long c_uint unsigned int int/long c_long long int/long c_ulong unsigned long int/long c_longlong __int64 or long long int/long c_ulonglong unsigned __int64 or unsigned long long int/long c_float float float c_double double float c_char_p char * (NUL terminated) string or None c_wchar_p wchar_t * (NUL terminated) unicode or None c_void_p void * int/long or None

2.操作int

>>> from ctypes import *  >>> c=c_int(34)  >>> c  c_int(34)  >>> c.value  34  >>> c.value=343  >>> c.value  343  

3.操作字符串

>>> p=create_string_buffer(10)  >>> p.raw  'x00x00x00x00x00x00x00x00x00x00'  >>> p.value='fefefe'  >>> p.raw  'fefefex00x00x00x00'  >>> p.value='fefeeeeeeeeeeeeeeeeeeeeeee'  #字符串太長,報錯  Traceback (most recent call last):    File "<stdin>", line 1, in <module>  ValueError: string too long  

4.操作指針

>>> i=c_int(999)  >>> pi=pointer(i)  >>> pi  <__main__.LP_c_int object at 0x7f7be1983b00>  >>> pi.value  Traceback (most recent call last):    File "<stdin>", line 1, in <module>  AttributeError: 'LP_c_int' object has no attribute 'value'  >>> pi.contents  c_int(999)  >>> pi.contents=c_long(34343)  >>> pi.contents  c_int(34343)   通過pointer獲取一個值的指針 通過contents獲取一個指針的值

5.c的結構體

#定義一個c的structure,包含兩個成員變量x和y  >>> class POINT(Structure):  ...     _fields_=[('x',c_int),('y',c_int)]  ...  >>> point=POINT(2,4)  >>> point  <__main__.POINT object at 0x7f7be1983b90>  >>> point.x,point.y  (2, 4)  >>> porint=POINT(y=2)  >>> porint  <__main__.POINT object at 0x7f7be1983cb0>  >>> point=POINT(y=2)  >>> point.x,point.y  (0, 2)  定義一個類型為POINT的數組  >>> POINT_ARRAY=POINT*3  >>> pa=POINT_ARRAY(POINT(2,3),POINT(2,4),POINT(2,5))  >>> for i in pa:print pa.y  ...  Traceback (most recent call last):    File "<stdin>", line 1, in <module>  AttributeError: 'POINT_Array_3' object has no attribute 'y'  >>> for i in pa:print i.y  ...  3  4  5  

6.訪問so文件

1.創建一個c文件

#include <stdio.h>  int hello_world(){      printf("Hello World");      return 0;  }  int main(){          hello_world();          return 0;  }  

2.編譯成動態連結庫

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

3.python中調用庫中的函數

from ctypes import cdll  c_lib=cdll.LoadLibrary('./hello_world.so')  c_lib.hello_world()  

二.測試c的性能和python的差別

sum.c

int sum(int num){      long sum=0;      int i =0;      for( i=1;i<=num;i++){          sum=sum+i;      };      return sum;  }  int main(){      printf("%d",sum(10));      return 0;  }   測試方案:計算1-100的和 測試次數:100萬次

1. 直接用c來執行,通linux 的time命令來記錄執行的用時

sum.c:

#include <stdio.h>  int sum(int num){      long sum=0;      int i =0;      for( i=1;i<=num;i++){          sum=sum+i;      };      return sum;  }  int main(){      int i ;      for (i=0;i<1000000;i++){      sum(100);      }      return 0;  }  

測試結果的例子:

real 1.16 user 1.13 sys 0.01

2.通過Python調用so文件和python的測試結果

sum_test.py:

def sum_python(num):      s = 0      for i in xrange(1,num+1):          s += i      return s        from ctypes import cdll     c_lib = cdll.LoadLibrary('./sum.so')        def sum_c(num):      return c_lib.sum(num)        def test(num):      import timeit         t1 = timeit.Timer('c_lib.sum(%d)' % num, 'from __main__ import c_lib')      t2 = timeit.Timer('sum_python(%d)' % num, 'from __main__ import sum_python')      print 'c', t1.timeit(number=1000000)      print 'python', t2.timeit(number=1000000)        if __name__ == '__main__':      test(100)  

測試結果的例子

c 1.02756714821  python 7.90672802925  

3.測試erlang的測試結果

剛剛學了erlang,那就一起測試一下erlang的運算性能

sum.erl:

-module(sum).  -export([sum/2,sum_test/2]).  sum(0,Sum) ->          Sum;  sum(Num,Sum) ->          sum(Num-1,Sum+Num).  sum_test(Num,0) ->          0;  sum_test(Num,Times) ->          sum(Num,0),          sum_test(Num,Times-1).  

調用:

timer:tc(sum,sum_test,[100,1000000]). 

測試結果的例子:

{2418486,0} 

4.測試結果

用上面的測試方法,進行10次測試,去除最大值和最小值,再計算平均值,得出:

單位:秒

求和的運行,使用的內存比較小,但是佔用CPU資源比較多。 原生的C是最快的,Python調用c會稍微慢一點,原因是計算100的和的操作是在c裡面做的,而執行100萬次的邏輯是在python做的 erlang的性能雖然比c稍慢,但是也是不錯的, Python的運行效率慘不忍睹。。。 

點讚 0

相關焦點

  • 雙劍合璧,Python調用C代碼
    但是與此同時,靈活的語言特性所帶來的代價是性能的降低。因此,Python在一些計算密集型的場景中,與一些底層語言,如C、C++相比,往往顯得力不從心。那麼,Python有沒有辦法在保持優秀語法特性的同時,還能夠在性能上得到提升呢?當然可以。既然C語言的效率高,那麼我們把程序中對性能要求較高的部分用C語言來實現就是一種解決方案。
  • 加速程序開發 Python整合C語言模塊
    Python是一種解釋型的,互動的,面向對象的程式語言,它包含了模塊化的操作,異常處理,動態資料形態,以及類型的使用。它的語法表達優美易讀,具有很多優秀的腳本語言的特點:解釋的,面向對象的,內建的高級數據結構,支持模塊和包,支持多種平臺,可擴展。而且它還支持交互式方式運行,圖形方式運行。它擁有眾多的編程界面支持各種作業系統平臺以及眾多的各類函數庫,利用C和C++可以對它進行擴充。
  • Python使用ctypes模塊調用DLL函數之C語言數組與numpy數組傳遞
    在Python語言中,可以使用ctypes模塊調用其它如C++語言編寫的動態連結庫DLL文件中的函數,在提高軟體運行效率的同時,也可以充分利用目前市面上各種第三方的DLL庫函數,以擴充Python軟體的功能及應用領域,減少重複編寫代碼、重複造輪子的工作量,這也充分體現了Python語言作為一種膠水語言所特有的優勢
  • Shell調用Python函數
    Shell腳本調用Python函數,本例子是通過Shell調用Python腳本,檢查伺服器上的某埠是否開啟,編寫的Python腳本port.py,腳本內容: port.py import socket def scan(port):    s = socket.socket()    s.settimeout(0.1) 
  • Python使用ctypes模塊調用DLL函數之複數數組的參數傳遞
    引言前段時間在作信號分析處理方面的項目時,需要將時域數據通過快速傅立葉變換(FFT)轉換到頻域以便作進一步的後續處理,由於涉及到實時運算速度方面的要求,需要考慮程序算法的運算性能問題,因此,信號處理算法是在C語言裡面完成的,然後將算法的實現函數封裝到動態連結庫(DLL)文件中,最後在
  • python 函數定義以及函數的調用
    參數的調用:位置參數關鍵字參數3. 在python中參數無類型,參數可以接受任意對象,只有函數中代碼才會對參數類型有限制4.調用函數時,所有傳入的 多餘的 位置參數都會被args接收生成一個元組。調用函數時,所有傳入的 多餘的 關鍵字參數都會被kwargs接收生成一個字典。總結:1.必備參數:在函數調用的時候,必備參數必須要傳入。
  • Qt使用C/C++擴展Python內置模塊
    之前和大家介紹過在C/C++中嵌入Python,本次和大家分享下使用C/C++擴展Python內置模塊的方法。被擴展出來的新模塊可以做兩件無法直接在Python中完成的事情:一可以實現新的內置對象類型,二則可以調用C庫函數和一些其他的系統調用。
  • 小白學Python——模塊的調用
    內置模塊(builtins)在解析器的內部可以直接使用標準庫模塊,安裝python時已經安裝可以直接使用第三方模塊(通常為開源),需要自己安裝pip3 install 模塊名或是 pip install 模塊名(通常用來安裝python3的模塊
  • python從入門到放棄 第一天 模塊和函數的兩種調用方式及區別
    前言雖然是搞IT類工作的,但是工作中比較少涉及到編程,偶爾因為數據分析或者運維的需要會寫一些SQL語句或者腳本,卻沒有正正經經地完整學個程式語言。雖然老早就想學學python搞個爬蟲,去網上抓些漂亮小姐姐的照片了,卻一直沒有騰出手來。現在趁著疫情比較閒,決定開始打卡學習。下面就是我的每日打卡心得,請大家監督,與大家一起共勉。
  • Python的武器庫01:builtwith模塊和python-whois模塊
    說到程式語言python,有一個著名的格言"餘生太短,只用python"。如果要分析為什麼會存在這麼一句格言?python的語法並不簡單,有複雜難懂的部分,之所以有這樣一句格言,是因為python中有很多強大的模塊,就像一個武器庫。
  • Python案例|混用C函數
    今天,我們來解決python的速度問題.我們平時所說的Python是指在PC機上的CPython,換句話說,Python的解釋器是用C語言編寫的。為Python編寫C擴展模塊能夠顯著提高Python的執行速度,眼下有好幾種方案可以完成這件事。
  • 淺談Python程序和C程序的整合
    Python 是一種解釋型的,互動的,面向對象的程式語言,它包含了模塊化的操作,異常處理,動態資料形態,以及類型的使用。它的語法表達優美易讀,具有很多優秀的腳本語言的特點:解釋的,面向對象的,內建的高級數據結構,支持模塊和包,支持多種平臺,可擴展。而且它還支持交互式方式運行,圖形方式運行。它擁有眾多的編程界面支持各種作業系統平臺以及眾多的各類函數庫,利用 C 和 C++ 可以對它進行擴充。
  • python使用ctypes模塊調用DLL函數之傳遞數值、指針與字符串參數
    在Python語言中,可以使用ctypes模塊調用其它如C++語言編寫的動態連結庫DLL文件中的函數,在提高軟體運行效率的同時,也可以充分利用目前市面上各種第三方的DLL庫函數,以擴充Python軟體的功能及應用領域,減少重複編寫代碼、重複造輪子的工作量,這也充分體現了Python語言作為一種膠水語言所特有的優勢。
  • 這才是正確寫Python的姿勢,你不過是在用Python
    Python可以通過c/c++語言來擴展我們自己的模塊,在Python.h中作者提供了基礎數據結構和方法,幫助我們在c/c++中調用Python的API,同時我們也可以用c/c++來封裝自己的模塊。編寫c/c++的代碼,並且需要調試是讓很多初級程式設計師很頭疼的一件事,但是為什麼還是要編寫c/c++呢?原因很簡單,但我們對性能要求比較高,或者程序處理數據的效率高,那麼我們就需要一些底層的語言來封裝我們處理數據的模塊,然後供Python來調用,Python是一門高級語言,開發效率很高,但是性能不及c/c++的。
  • python sys 模塊
    sys模塊提供了一系列有關Python運行環境的變量和函數sys.argv功能:在外部向程序內部傳遞參數方法:sys.argv返回值:list/* 獲取當前正在執行的命令行參數的參數列表value is argv_test.py 39;str& 第一個傳參argv2: type is <class &39;>, value is a 39;str& 第 &39; 個傳參argv4: type is <class &39;>, value is b 39;str& ...argv6: type is <class &39;>, value is c
  • Python 性能優化的20條招數
    使用C擴展(Extension)目前主要有 CPython(python最常見的實現的方式)原生API, ctypes,Cython,cffi三種方式,它們的作用是使得 Python 程序可以調用由C編譯成的動態連結庫,其特點分別是:CPython 原生 API: 通過引入 Python.h 頭文件,對應的C程序中可以直接使用Python 的數據結構
  • 少兒編程學習必備,Python以及Pygame、pip模塊的安裝教程
    鑑於有諸多同學對於遊戲製作以及模塊安裝出現了諸多問題(其實是碼趣君忘記預先告知了),碼趣君決定詳細解答安裝時所需要的步驟,幫助所有同學在製作遊戲時不會出現報錯或者模塊缺失的情況,下面就讓我們來看一下吧。
  • Python的武器庫05:numpy模塊(下)
    說到程式語言python,有一個著名的格言"餘生太短,只用python"。如果要分析為什麼會存在這麼一句格言?python的語法並不簡單,有複雜難懂的部分,之所以有這樣一句格言,是因為python中有很多強大的模塊,就像一個武器庫。
  • Python語法基礎(15)模塊與包
    模塊分為以下三種:內置標準模塊(又稱標準庫)執行help(&39;)查看所有python自帶模塊列表第三方開源模塊,可通過 pip install 模塊名 安裝自定義模塊包- pg2|- - __init__.py|- - c.py|- - d.pya.pydef a():    print(&39;
  • PHP調用Python快速發送高並發郵件
    但是PHP底層的socket編程相對於python來說效率是非常低的。CleverCode同時寫過用python寫的爬蟲抓取網頁,和用php寫的爬蟲抓取網頁。發現雖然用了php的curl抓取網頁,但是涉及到超時,多線程同時抓取等等。不得不說python在網絡編程的效率要比PHP好的多。