python 程序中調用go


Golang構建Python高性能模塊

雖然Python優點很多,但是有一個致命的缺點就是運行速度太慢,那么Python程序需要一些計算量比較大的模塊時一般會調用c或者c++的代碼來重寫,但是c/c++編寫代碼代價太高,耗費太多的人力,開發周期太長,那么就想到來一個折中的方法是用golang語言。

雖然golang性能比不上c、c++,但是golang天生的高並發,以及編譯速度超級快,而且還自帶垃圾回收機制,不用開發者自己去管理內存,開發效率高。所以在Python程序遇到大計算量時,可以考慮調用go模塊。接下來我們來看看如何在利用go模塊寫Python第三方模塊,以及如何在Python中導入並調用。

下面構建一個go python 模塊:

package main
import "C"
​
//指定那些函數能被外部調用
//export test
func test()  int{
    //計算 0-100000 的和
    var s int
    for a := 0; a <= 1000000; a++ {
        s += a 
     }
     return s
} 
​
func main(){
}
 

  

編譯生成動態鏈接庫,生成的.so文件可以被python加載並調用

但是有一個需要注意的地方:

Python是利用ctypes來跟so模塊進行交互,其中存在着一個代碼的翻譯過程,包括數據類型的翻譯,如果需要傳參獲取接收返回值,需要在golang中將參數按照下表對應,定義成C語言的數據類型。

python,ctypes , c 對應類型參考 python 官方文檔:https://docs.python.org/3.5/library/ctypes.html

這里列舉幾個常用的數據類型

ctypes type(ctypes類型) C type(c語言類型) Python type(python類型)
c_bool _Bool bool (1)
c_char char 1-character bytes object
c_wchar wchar_t 1-character string
c_byte char int
c_char_p char * (NUL terminated) 1-character bytes object
c_wchar_p wchar_t * (NUL terminated) string or None

 

比如創建一個帶參數的go函數:


// 指定接收的參數為c類型的字符串,返回c類型字符串
//pxport addstr
func addstr(a,b * C.char) *C.char{
        merge := C.GoString(a) + C.GoString(b)
        return C.CString(merge)
​
}

  

 
寫好go代碼之后重新生成動態鏈接庫

go build -buildmode=c-shared -o hello.so src/hello.go

在python中調用帶參數的go模塊需要顯式指定參數的類型以及返回的數據類型。argtypes指定參數類型,restype

指定返回值類型。

from ctypes import CDLL
add = CDLL('./hello.so').addstr  #調用go模塊
# 顯式聲明參數和返回的期望類型
add.argtypes = [ctypes.c_char_p, ctypes.c_char_p]
add.restype = ctypes.c_char_p
print(add('haha','hehe'))
​
# 無參數,則可直接調用
t = CDLL('./hello.so').test #調用go模塊
print(t())
    

  


python 中調用go模塊,並統計兩個模塊循環1百萬次累加的時間,查看go跟python執行效率

# coding=utf-8
import time
from ctypes import CDLL
import ctypes
​
def xu():
    # python 計算累加
    sum = 0
    for i in range(0,1000000+1):
        sum += i
    return sum
​
if __name__ =="__main__":
​
​
    add = CDLL('./hello.so').addstr  #調用go模塊addstr方法
    # 顯式聲明參數和返回的期望類型
    add.argtypes = [ctypes.c_char_p, ctypes.c_char_p]
    add.restype = ctypes.c_char_p
​
    print(add('haha','hehe'))
​
    # go 一百萬次累加
    start  = time.time()
    t = CDLL('./hello.so').test #調用go模塊test方法
    t.restype = ctypes.c_int64    # 返回int64類型
    print("go執行結果:%s"%t())
    end = time.time()
    print("go :1000000 累加耗時 %.2f" %(end-start))
​
    # python累加一百萬次 
    start  = time.time()
    print("python執行結果:%s"%xu())
    end = time.time()
    print("python :1000000 累加耗時 %.2f" %(end-start))
​

  


單從循環一百萬次來看,go的效率要高很多。

 

Python 號稱開發速度快,而go語言在靜態語言中也號稱是開發開發速度最快的,go的高並發剛好可以填補Python GIL導致Python多線程不是真的多線程這一缺點。

本文主要講解了如何使用golang寫Python模塊,以及在Python中如何調用go模塊,主要要注意的是參數類型的轉換。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM