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

  • 相关阅读:
    ligerui_ligerTree_007_ligerTree动态加载节点
    ligerui_ligerTree_006_ligerui事件支持
    ligerui_ligerTree_005_动态增加“树”节点
    ligerui_ligerTree_004_对"ligerTree"节点操作
    ligerui_ligerTree_003_配置url参数,加载“树”
    ligerui_ligerTree_002_利用JavaScript代码配置ligerTree节点
    ligerui_ligerTree_001_第一个“树”效果
    ligerui_实际项目_003:form中添加数据,表格(grid)里面显示,最后将表格(grid)里的数据提交到servlet
    ligerui+json_002_Grid用法、属性总结
    ligerui+json_001_实现表格(grid)的后台数据显示、分页
  • 原文地址:https://www.cnblogs.com/huangguifeng/p/8931837.html
Copyright © 2020-2023  润新知