Python × Go：PythonからGoを呼び出して実行速度を改善する方法


[![Group189.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3967621/4266bee4-16b8-475c-b97f-56fb29313bb4.png)](https://leapcell.io/)


**[Leapcell: The Best of Serverless Web Hosting](https://leapcell.io/)**

# PythonとGoの組み合わせ：動的リンクライブラリを利用して開発と計算効率を向上させる

今日のソフトウェア開発の状況において、PythonとGoはともに非常に人気のあるプログラミング言語であり、それぞれ独自の利点を持っています。Pythonは、簡潔でエレガントな構文と豊富なライブラリで知られており、開発効率を大幅に高めます。データサイエンス、人工知能、ウェブスクレイピングなどの分野で広く応用されています。一方、Go言語は静的型付けでコンパイル型の言語です。優れた並列処理性能と高い実行効率を誇り、高性能なネットワークサービス、分散システム、システムレベルのプログラミングシナリオの構築によく使われます。

一部の複雑なプロジェクトの開発を行う際、私たちはしばしばこの2つの言語の強みを最大限に生かしたいと考えます。例えば、複雑な計算部分をGoで開発し、動的リンクライブラリにコンパイルしてから、Pythonで呼び出すことができます。このようにすることで、Pythonの開発の利便性を生かしつつ、Goの効率的な計算能力も活用することができ、開発効率と計算速度を向上させるという目的を達成することができます。

## 動的リンクライブラリの紹介
動的リンクライブラリ（略称：DLL）ファイルは、非実行可能なバイナリプログラムファイルです。その主な機能は、実行中のプログラムが特定のタスクを実行するために必要なコードとリソースを共有できるようにすることです。動的リンクライブラリは、異なるオペレーティングシステムでは異なるファイル拡張子を持ちます。Windowsオペレーティングシステムでは、動的リンクライブラリはしばしば`.dll`拡張子で終わります；一方、Linuxシステムでは、動的リンクライブラリは通常`.so`拡張子で終わります。

動的リンクの原理は、いくつかの共通して共有されるコードからDLLファイルを作成することです。実行可能ファイルがDLLファイル内の関数を呼び出すと、WindowsオペレーティングシステムはDLLファイルをメモリにロードします。DLLファイル自体の構造は実行可能ファイルであり、関数はプログラムがそれらを必要とするときにのみリンクされます。この動的リンク方法により、メモリの無駄遣いの状況を大幅に減らすことができます。対照的に、静的リンクは必要なコードを直接実行可能ファイルにリンクします。DLLの元々の設計目的は、アプリケーションプログラムが必要とするディスクとメモリのスペースを節約することでした。

## Goのコード例
ここでは、簡単なGoのコード例を示します。`add.go`ファイルとして保存してください：
```go
package main

import "C"  // Cライブラリは必ずインポートする必要がある

import "fmt"

// 以下のコメントアウトされたコードを追加し、エクスポート後にPythonから呼び出せることを示す
// 注意：以下のコメントは"// export xxx"と書かないで、"//export xxx"と書く必要がある
// そうしないと、呼び出すことができない

//export PrintDll
func PrintDll() {
    fmt.Println("I come from the GO dynamic link library")
}

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

func main() {
    // CGOコンパイルのエントリポイントとしてmain関数を追加する必要があり、具体的な実装コードはなくてもよい
}
```
このコードでは、`PrintDll`と`Add`の2つの関数を定義し、特別なコメント`//export`を通じてこれらの関数がPythonから呼び出せるようにマークしました。同時に、`main`関数には具体的な実装コードはありませんが、CGOコンパイルのエントリポイントとして必要です。

## 動的リンクライブラリファイルにコンパイルする
異なるオペレーティングシステムは異なる環境を持っているため、`add.go`ソースファイルをコンパイルする方法も異なります。以下では、プラットフォーム別に紹介します：
### LinuxとMac
一般的に、Linuxシステムには`gcc`ソフトウェアが事前にインストールされており、以下のコマンドを直接使ってコンパイルすることができます：
```bash
go build -buildmode=c-shared -o add.so add.go
```
上記のコマンドにより、`add.go`は`add.so`動的リンクライブラリファイルにコンパイルされます。

### Windows
Windowsでコンパイルするには、まずMinGWソフトウェアをインストールする必要があります。インストールが完了したら、`gcc`を使うことができます。コンパイルコマンドは以下の通りです：
```bash
go build -buildmode=c-shared -o add.dll add.go
```
このコマンドにより、`add.go`は`add.dll`動的リンクライブラリファイルにコンパイルされます。

## コンパイル結果の最適化
通常の状況では、上記のコンパイル方法で得られる動的リンクライブラリファイルは比較的大きくなります。これもまた、Go言語がしばしば批判される問題の一つです。しかし、以下のアプローチを使うことで、コンパイルされたファイルのサイズをある程度削減することができます：
```bash
go build -ldflags "-s -w" -buildmode=c-shared -o add.so add.go
```
このうち、`-s`は圧縮を示します；`-w`はデバッグ情報を削除することを示します。このようにすることで、動的リンクライブラリファイルのサイズを効果的に削減することができます。

## Pythonで動的リンクライブラリファイルを呼び出す
コンパイルされた動的リンクライブラリファイルをPythonで呼び出すには、`ctypes`モジュールを使う必要があります。具体的な呼び出し方法は以下の通りです：
```python
# Test calling code written in the GO language from Python
# First, the GO code needs to be compiled into a dynamic link library

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ノートブックで直接実行することができます。また、`add.py`ファイルとして保存して、コマンドラインで実行することもできます：
```bash
time python add.py
```
実行結果は以下の通りです：
```
result 300
I come from the GO dynamic link library
python add.py  0.02s user 0.01s system 20% cpu 0.030 total
```
以上のステップを通じて、私たちはPythonでGo言語で書かれた動的リンクライブラリを成功裏に呼び出すことができました。これにより、両方の言語の利点を最大限に生かし、開発効率と計算速度を向上させることができました。 

# [Leapcell: The Best of Serverless Web Hosting](https://leapcell.io/)

最後に、Go/Pythonサービスのデプロイに最適なプラットフォームをおすすめします：**[Leapcell](https://leapcell.io/)**

[![brandpic7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3967621/3dbb7522-9672-4802-81a1-5fe15b714beb.png)](https://leapcell.io/)


### 🚀 好きな言語で構築する
JavaScript、Python、Go、またはRustで簡単に開発できます。  

### 🌍 無料で無制限のプロジェクトをデプロイする
使用する分だけ支払うだけです—リクエストがなければ、請求はありません。  

### ⚡ 使った分だけ支払い、隠したコストはなし
アイドル料金はなく、シームレスなスケーラビリティがあります。  

[![Frame3-withpadding2x.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3967621/efdf35f7-5a18-4d97-b90b-e727fb02acee.png)](https://leapcell.io/)


[📖 ドキュメントを探索する](https://docs.leapcell.io/)  

🔹 Twitterでフォローしてください：[@LeapcellHQ](https://x.com/LeapcellHQ)