Python2.7中如何导入Github上的Golang模块并调用其函数
Python2.7调用Github托管Go包函数的可行方案
Python本身没有直接导入Go源码包的能力,针对你的场景(Python2.7环境、支持传参、获取返回值),有两类落地性强的方案,优先推荐第一种动态库调用方案,性能和兼容性最好。
方案一:cgo编译共享库 + ctypes调用(推荐)
这个方案不需要额外安装第三方依赖,在Python2.7全版本下都能稳定运行,调用性能接近原生函数调用。
步骤1:拉取Go包代码并改造导出接口
先把Github上的Go包代码拉到本地,由于Go的原生函数符号不满足C调用规范,需要给要调用的函数加cgo导出标记,做C类型适配,改造示例:
package main import "C" import "unsafe" //export NewFromStrings func NewFromStrings(inputs **C.char, inputLen C.int) *C.char { // 将C传入的字符串数组转换为Go原生[]string类型 goInput := make([]string, int(inputLen)) ptrStep := unsafe.Sizeof(uintptr(0)) basePtr := uintptr(unsafe.Pointer(inputs)) for i := 0; i < int(inputLen); i++ { cStr := *(**C.char)(unsafe.Pointer(basePtr + uintptr(i)*ptrStep)) goInput[i] = C.GoString(cStr) } // 此处替换为原包的实际业务逻辑 ret := "abc" // 转换为C兼容的字符串类型返回 return C.CString(ret) } // 编译为共享库必须保留空main函数 func main() {}
步骤2:编译为对应系统的动态链接库
在Go代码目录执行对应编译命令,生成Python可加载的动态库:
- Linux:执行
go build -buildmode=c-shared -o libgofile.so go_file.go,生成libgofile.so文件 - Windows:执行
go build -buildmode=c-shared -o go_file.dll go_file.go,生成go_file.dll文件 - macOS:执行
go build -buildmode=c-shared -o libgofile.dylib go_file.go,生成libgofile.dylib文件
步骤3:Python2.7侧加载调用
使用Python2.7内置的ctypes库加载编译好的动态库,完成参数转换和调用:
import ctypes # 加载对应系统的动态库文件,路径替换为实际存放路径 lib = ctypes.CDLL("./libgofile.so") # 声明函数的入参、出参类型,避免默认类型转换错误 lib.NewFromStrings.argtypes = (ctypes.POINTER(ctypes.c_char_p), ctypes.c_int) lib.NewFromStrings.restype = ctypes.c_char_p # 准备Python侧入参 str_list = ["abc", "def"] # 转换为C要求的字符串数组格式 c_args = (ctypes.c_char_p * len(str_list))() for idx, s in enumerate(str_list): c_args[idx] = s # 调用函数获取结果 res = lib.NewFromStrings(c_args, len(str_list)) print res
注意:上述示例中Go侧用
C.CString返回的字符串是在堆上分配的内存,长期运行需要额外在Go侧写一个内存释放函数,Python拿到结果后主动调用释放,避免内存泄漏。
方案二:本地服务封装调用
如果不想处理复杂的C类型转换、内存管理逻辑,可以把Go函数封装成本地HTTP服务:
- Go侧引入net/http包,把
NewFromStrings封装为本地监听的HTTP接口,接收JSON格式的字符串列表参数,处理后返回JSON结果 - Python2.7侧用内置的urllib2库向本地端口发请求,传参拿结果
这个方案开发调试成本低,没有跨语言兼容问题,缺点是多了一层本地网络IO开销,适合对调用延迟不敏感的场景。
避坑说明
不要尝试用gopy、pybind等第三方Go-Python绑定工具,这类工具基本都已经停止对Python2.7的适配,会出现大量编译、运行时兼容问题,调试成本远高于上述两种方案。
内容的提问来源于stack exchange,提问作者Sanjit P
相关产品推荐
相关产品推荐

