• 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模块,主要要注意的是参数类型的转换。

  • 相关阅读:
    WebAssembly API & MDN All In One
    Apple iPhone 14 Pro 药丸设计看不懂,药丸上面那条屏幕缝隙完全没有用处呀?
    API 调试工具 All In One
    macOS Time Machine All In One
    使用 macOS 输入多个空格,会自动添加一个点 bug All In One
    手把手的教你如何使用 Vite 搭建一个 React UI 组件库 All In One
    LeetCode 两数相加算法题解 All In One
    如何把 iPad 作为 Mac 扩展屏幕使用 All In One
    【DEMO】【C/C++】最简单的一种回调函数
    Qt中cvMat与QImage,QPixmap的转换
  • 原文地址:https://www.cnblogs.com/huangguifeng/p/8931837.html
Copyright © 2020-2023  润新知