如何在Python中调用Go代码:用Go加速Python

结合Python和Go:利用动态链接库提升开发和计算效率

在当今的软件开发环境中,Python和Go都是非常流行的编程语言,各自拥有独特的优势。Python以其简洁优雅的语法和丰富的库而闻名,这大大提高了开发效率。它广泛应用于数据科学、人工智能和网络爬虫等领域。另一方面,Go语言是一种静态类型的编译语言。它具有出色的并发性能和高运行效率,通常用于构建高性能的网络服务、分布式系统和系统级编程场景。

在进行一些复杂项目的开发时,我们常常希望充分利用这两种语言的优势。例如,我们可以使用Go开发复杂的计算部分,将其编译成动态链接库,然后在Python中调用。通过这种方式,我们可以利用Python的开发便利性,同时也能发挥Go的高效计算能力,从而实现提高开发效率和计算速度的目标。

动态链接库简介

动态链接库(简称 DLL)文件是一种非可执行的二进制程序文件。其主要功能是使正在运行的程序能够共享执行特定任务所需的代码和资源。动态链接库在不同操作系统中有不同的文件扩展名。在 Windows 操作系统中,动态链接库通常以 .dll 扩展名结尾;而在 Linux 系统中,动态链接库通常以 .so 扩展名结尾。

动态链接的原理是从一些常用的共享代码中创建 DLL 文件。当可执行文件调用 DLL 文件中的函数时,Windows 操作系统会将 DLL 文件加载到内存中。DLL 文件本身的结构是一个可执行文件,只有当程序需要时,函数才会被链接。通过这种动态链接方式,可以大大减少内存浪费的情况。相对而言,静态链接则是将所需的代码直接链接到可执行文件中。DLL 的最初设计目的就是为了节省应用程序所需的磁盘和内存空间。

Go 代码示例

这里我们提供一个简单的 Go 代码示例。将其保存为 add.go 文件:

package main

import "C"  // 必须导入C库

import "fmt"

// 添加以下注释代码,表示导出后可以被Python调用
// 注意,以下注释不应写为 "// export xxx",而应写为 "//export xxx"
// 否则无法被调用

//export PrintDll
func PrintDll() {
    fmt.Println("我来自GO动态链接库")
}

//export Add
func Add(a int, b int) int {
    return a + b
}

func main() {

// 必须添加一个主函数作为CGO编译的入口点,且不需要具体的实现代码
}

在这段代码中,我们定义了两个函数,PrintDllAdd,并通过特殊注释//export标记这些函数可以从Python调用。同时,尽管main函数没有具体的实现代码,但它作为CGO编译的入口点是必要的。
编译成动态链接库文件

由于不同的操作系统具有不同的环境,因此编译 add.go 源文件的方法也有所不同。下面我们将按平台进行介绍:

Linux 和 Mac

一般来说,Linux 系统预装了 gcc 软件,我们可以直接使用以下命令进行编译:

go build -buildmode=c-shared -o add.so add.go

上述命令将把 add.go 编译成 add.so 动态链接库文件。

Windows

在Windows上编译

要在Windows上进行编译,您需要先安装MinGW软件。安装完成后,您可以使用gcc。编译命令如下:

go build -buildmode=c-shared -o add.dll add.go

此命令将把add.go编译成add.dll动态链接库文件。

优化编译结果

在正常情况下,通过上述编译方法获得的动态链接库文件相对较大,这也是Go语言经常受到批评的问题。然而,我们可以使用以下方法在一定程度上减小编译文件的大小:

go build -ldflags "-s -w" -buildmode=c-shared -o add.so add.go

其中,-s表示压缩;-w表示去除调试信息。通过这种方式,可以有效减小动态链接库文件的大小。

在Python中调用动态链接库文件

要在Python中调用编译好的动态链接库文件,我们需要使用ctypes模块。具体的调用方法如下:

# 从Python调用用GO语言编写的代码
# 首先,GO代码需要编译成动态链接库

from ctypes import cdll

lib = cdll.LoadLibrary("./add.so")  # 在这里指定编译好的动态链接库文件

# 调用GO语言中的Add函数
result = lib.Add(100, 200)
print("result ", result)

# 在GO语言中调用PrintDll函数
lib.PrintDll()

上述Python代码可以直接在Jupyter Notebook中运行。您也可以将其保存为add.py文件,然后在命令行中执行:

time python add.py

运行结果如下:

result 300
我来自GO动态链接库
python add.py  0.02s user 0.01s system 20% cpu 0.030 total

通过上述步骤,我们成功地在Python中调用了用Go语言编写的动态链接库,充分利用了两种语言的优势,提高了开发效率和计算速度。

更多