欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Golang如何調(diào)用Python代碼詳解

 更新時(shí)間:2018年10月14日 10:06:45   作者:白細(xì)胞  
這篇文章主要給大家介紹了關(guān)于Golang如何調(diào)用Python代碼的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧

前言

Python是時(shí)髦的機(jī)器學(xué)習(xí)御用開發(fā)語(yǔ)言,Golang是大紅大紫的新時(shí)代后端開發(fā)語(yǔ)言。Python很適合讓搞算法的寫寫模型,而Golang很適合提供API服務(wù),兩位同志都紅的發(fā)紫,這里就介紹一下正確攪基的辦法。

go 中的 cgo 模塊可以讓 go 無(wú)縫調(diào)用 c 或者 c++ 的代碼,而 python 本身就是個(gè) c 庫(kù),自然也可以由 cgo 直接調(diào)用,前提是指定正確的編譯條件,如 Python.h 頭文件(),以及要鏈接的庫(kù)文件。本文以 Ubuntu 18.04 作為開發(fā)和運(yùn)行平臺(tái)進(jìn)行演示。

其實(shí)在使用 cgo 之前,筆者也考慮過使用 grpc 的方式。比如可以將需要調(diào)用的 python 代碼包裝成一個(gè) grpc server 端,然后再使用 go 編寫對(duì)應(yīng)的 client 端,這樣考慮的前提是,go 調(diào)用 python 代碼本來(lái)就是解一時(shí)之困,而且引入語(yǔ)言互操作后,對(duì)于項(xiàng)目維護(hù)和開發(fā)成本控制都有不小的影響,如果直接使用 grpc 生成編程語(yǔ)言無(wú)感知的協(xié)議文件,將來(lái)無(wú)論是重構(gòu)或使用其他語(yǔ)言替換 python 代碼,都是更加方便,也是更加解耦的。所以 grpc 也是一種比較好的選擇。至于通信延遲,老實(shí)說(shuō)既然已經(jīng)設(shè)計(jì)語(yǔ)言互操作,本機(jī)中不到毫秒級(jí)的損失其實(shí)也是可以接受的。

接下來(lái)進(jìn)入正題。

Golang調(diào)用Python代碼

1. 針對(duì) python 版本安裝 python-dev

sudo apt install python3.6-dev

系統(tǒng)未默認(rèn)安裝 python3.x 的開發(fā)環(huán)境,所以假如要通過 cgo 調(diào)用 python,需要安裝對(duì)應(yīng)版本的開發(fā)包。

2. 指定對(duì)應(yīng)的cgo CFLAGS 和 LDFLAGS 選項(xiàng)

對(duì)于未由 c 包裝的 python 代碼,python-dev 包中內(nèi)置了 python-config 工具用于查看編譯選項(xiàng)。

python3.6-config --cflags

python3.6-config --ldflags

以下是對(duì)應(yīng)的輸出

-I/usr/include/python3.6m -I/usr/include/python3.6m  -Wno-unused-result -Wsign-compare -g -fdebug-prefix-map=/build/python3.6-MtRqCA/python3.6-3.6.6=. -specs=/usr/share/dpkg/no-pie-compile.specs -fstack-protector -Wformat -Werror=format-security  -DNDEBUG -g -fwrapv -O3 -Wall

-L/usr/lib/python3.6/config-3.6m-x86_64-linux-gnu -L/usr/lib -lpython3.6m -lpthread -ldl  -lutil -lm  -xlinker -export-dynamic -Wl,-O1 -Wl,-Bsymbolic-functions

低版本的 python 也可以在安裝開發(fā)包后,使用對(duì)應(yīng)的 python-config 命令打印依賴配置。由于 cgo 默認(rèn)使用的編譯器不是 gcc ,所以輸出中的部分選項(xiàng)并不受支持,所以最后 cgo 代碼的配置為

//#cgo CFLAGS : -I./ -I/usr/include/python3.6m
//#cgo LDFLAGS: -L/usr/lib/python3.6/config-3.6m-x86_64-linux-gnu -L/usr/lib -lpython3.6m -lpthread -ldl  -lutil -lm
//#include "Python.h"
import "C"

3. 部分示例代碼

3.0 映射 PyObject

type PyObject struct {
 ptr *C.PyObject
}

func togo(obj *C.PyObject) *PyObject {
 if obj == nil {
  return nil
 }
 return &PyObject{ptr: obj}
}

func topy(self *PyObject) *C.PyObject {
 if self == nil {
  return nil
 }
 return self.ptr
}

3.1 python 環(huán)境的啟動(dòng)與終結(jié)

func Initialize() error {
 if C.Py_IsInitialized() == 0 {
  C.Py_Initialize()
 }
 if C.Py_IsInitialized() == 0 {
  return fmt.Errorf("python: could not initialize the python interpreter")
 }

 if C.PyEval_ThreadsInitialized() == 0 {
  C.PyEval_InitThreads()
 }
 if C.PyEval_ThreadsInitialized() == 0 {
  return fmt.Errorf("python: could not initialize the GIL")
 }

 return nil
}

func Finalize() error {
 C.Py_Finalize()
 return nil
}

3.2 包路徑與模塊導(dǎo)入

func InsertExtraPackageModule(dir string) *PyObject {
 sysModule := ImportModule("sys")
 path := sysModule.GetAttrString("path")

 cstr := C.CString(dir)
 defer C.free(unsafe.Pointer(cstr))
 C.PyList_Insert(topy(path), C.Py_ssize_t(0), topy(togo(C.PyBytes_FromString(cstr))))

 return ImportModule(dir)
}

func ImportModule(name string) *PyObject {
 c_name := C.CString(name)
 defer C.free(unsafe.Pointer(c_name))
 return togo(C.PyImport_ImportModule(c_name))
}

func (self *PyObject) GetAttrString(attr_name string) *PyObject {
 c_attr_name := C.CString(attr_name)
 defer C.free(unsafe.Pointer(c_attr_name))
 return togo(C.PyObject_GetAttrString(self.ptr, c_attr_name))
}

3.3 數(shù)據(jù)類型轉(zhuǎn)換

func PyStringFromGoString(v string) *PyObject {
 cstr := C.CString(v)
 defer C.free(unsafe.Pointer(cstr))
 return togo(C.PyBytes_FromString(cstr))
}

func PyStringAsGoString(self *PyObject) string {
 c_str := C.PyBytes_AsString(self.ptr)
 return C.GoString(c_str)
}

...

可以看到形似 C.Py* 的方法都是由 cgo 模塊編譯調(diào)用的,這些方法也是 python 暴露的C-API ,而這里的示例就到此為止,其他諸如調(diào)用 python 模塊方法的功能文檔里也描述得十分詳細(xì),盡管實(shí)施起來(lái)仍然有些麻煩。

但是請(qǐng)注意 C-API 的 2.x 與 3.x 版本仍有不同,比如 2.x 版本中的字符串操作類型 PyString_* 在 3.x 中便被重命名為 PyBytes_* 。

關(guān)注過 go 與 python 互操作功能的同學(xué)應(yīng)該注意到上述的示例代碼部分來(lái)自 go-python 這個(gè)開源項(xiàng)目,有興趣的同學(xué)也可以關(guān)注一下。 這個(gè)項(xiàng)目基于 python2.7 ,其中暴露的 api 諸如字符串轉(zhuǎn)換也是基于 python2.x 版本,所以針對(duì)于更流行的 python3.x 項(xiàng)目,大家就需要自己按照上文方法做一些修改了。

實(shí)際工作中,語(yǔ)言的互操作場(chǎng)景確實(shí)很讓人感覺頭疼,而 cgo 的文檔資料其實(shí)并不多,所以希望本文能給大家?guī)?lái)一些幫助。

總結(jié)

以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,如果有疑問大家可以留言交流,謝謝大家對(duì)腳本之家的支持。

相關(guān)文章

  • golang框架中跨服務(wù)的最佳通信協(xié)議和工具

    golang框架中跨服務(wù)的最佳通信協(xié)議和工具

    在 go 框架中實(shí)現(xiàn)跨服務(wù)通信的最佳實(shí)踐包括使用 grpc(適用于低延遲高吞吐量)、http 客戶端(適用于 restful api)和消息隊(duì)列(適用于異步解耦通信),在選擇通信方式時(shí),應(yīng)考慮服務(wù)交互模式、性能要求和部署環(huán)境等因素
    2024-06-06
  • 淺談golang 中time.After釋放的問題

    淺談golang 中time.After釋放的問題

    這篇文章主要介紹了淺談golang 中time.After釋放的問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來(lái)看看吧
    2021-05-05
  • Golang try catch與錯(cuò)誤處理的實(shí)現(xiàn)

    Golang try catch與錯(cuò)誤處理的實(shí)現(xiàn)

    社區(qū)不少人在談?wù)?nbsp;golang 為毛不用try/catch模式,而采用苛刻的recovery、panic、defer組合,本文就來(lái)詳細(xì)的介紹一下,感興趣的可以了解一下
    2021-07-07
  • 使用?pprof?進(jìn)行性能分析的方法詳解

    使用?pprof?進(jìn)行性能分析的方法詳解

    pprof?是?Go?語(yǔ)言中用于性能分析的一個(gè)強(qiáng)大工具,它可以幫助開發(fā)人員找到應(yīng)用程序中的性能瓶頸,并提供詳細(xì)的分析報(bào)告,本文將介紹如何使用?pprof?進(jìn)行性能分析,需要的朋友可以參考下
    2023-05-05
  • golang內(nèi)存逃逸的學(xué)習(xí)筆記

    golang內(nèi)存逃逸的學(xué)習(xí)筆記

    內(nèi)存逃逸是 Go 語(yǔ)言編程中一個(gè)特別需要注意的問題,會(huì)影響到程序的性能和穩(wěn)定性,本文主要介紹了golang內(nèi)存逃逸的學(xué)習(xí)筆記,感興趣的可以了解一下
    2024-05-05
  • golang新手不注意可能會(huì)出現(xiàn)的一些小問題

    golang新手不注意可能會(huì)出現(xiàn)的一些小問題

    最近在學(xué)習(xí)golang,發(fā)現(xiàn)了一些新手們需要注意的小問題,下面這篇文章主要給大家介紹了關(guān)于golang新手不注意可能會(huì)出現(xiàn)的一些小問題,文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考借鑒,下面來(lái)一起看看吧。
    2017-12-12
  • Go基礎(chǔ)語(yǔ)法的使用

    Go基礎(chǔ)語(yǔ)法的使用

    本文主要介紹了Go基礎(chǔ)語(yǔ)法的使用,包括標(biāo)識(shí)符、關(guān)鍵字、行分隔符、var關(guān)鍵字、:=運(yùn)算符、空格、注釋、package、import、輸入輸出、運(yùn)算符、條件控制、循環(huán)等,感興趣的可以了解一下
    2023-11-11
  • Go語(yǔ)言利用接口實(shí)現(xiàn)鏈表插入功能詳解

    Go語(yǔ)言利用接口實(shí)現(xiàn)鏈表插入功能詳解

    這篇文章主要為大家介紹了Go語(yǔ)言中的接口,以及如何利用接口實(shí)現(xiàn)鏈表插入功能,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以了解一下
    2022-04-04
  • Golang基礎(chǔ)學(xué)習(xí)之map的示例詳解

    Golang基礎(chǔ)學(xué)習(xí)之map的示例詳解

    哈希表是常見的數(shù)據(jù)結(jié)構(gòu),有的語(yǔ)言會(huì)將哈希稱作字典或者映射,在Go中,哈希就是常見的數(shù)據(jù)類型map,本文就來(lái)聊聊Golang中map的相關(guān)知識(shí)吧
    2023-03-03
  • 詳解Go語(yǔ)言如何判斷兩個(gè)對(duì)象是否相等

    詳解Go語(yǔ)言如何判斷兩個(gè)對(duì)象是否相等

    在編程中,判斷兩個(gè)對(duì)象是否相等是一項(xiàng)常見的任務(wù),同時(shí)判斷對(duì)象是否相等在很多情況下都非常重要,所以在接下來(lái)的內(nèi)容中,我們將詳細(xì)介紹在?Go?語(yǔ)言中如何判斷對(duì)象是否相等的方法和技巧,需要的可以參考一下
    2023-06-06

最新評(píng)論