pyproc — CGOやマイクロサービスなしでGoからPythonを呼び出す
(github.com/YuminosukeSato)私は pyproc を作りました。これにより、GoサービスからPythonをローカル関数のように呼び出せます — CGO不要、別個のマイクロサービスも不要 です。これはPythonワーカープロセスのプールを実行し、同一ホスト/Pod上で Unix Domain Sockets を介して通信するため、低オーバーヘッド、プロセス分離、そしてGILを超える並列性を実現できます。
これが存在する理由
- Goサービスを維持したまま、Python/NumPy/pandas/PyTorch/scikit-learnを再利用できます。
- 別個のPythonサービスに伴うネットワークホップ、サービスディスカバリ、運用負荷を避けられます。
すぐ試す(約5分)
Go(アプリ):
go get github.com/YuminosukeSato/pyproc@latest
Python(ワーカー):
pip install pyproc-worker
最小構成のワーカー(Python):
from pyproc_worker import expose, run_worker
@expose
def predict(req):
return {"result": req["value"] * 2}
if __name__ == "__main__":
run_worker()
Goから呼び出す:
import (
"context"
"fmt"
"github.com/YuminosukeSato/pyproc/pkg/pyproc"
)
func main() {
pool, _ := pyproc.NewPool(pyproc.PoolOptions{
Config: pyproc.PoolConfig{Workers: 4, MaxInFlight: 10},
WorkerConfig: pyproc.WorkerConfig{SocketPath: "/tmp/pyproc.sock", PythonExec: "python3", WorkerScript: "worker.py"},
}, nil)
_ = pool.Start(context.Background())
defer pool.Shutdown(context.Background())
var out map[string]any
_ = pool.Call(context.Background(), "predict", map[string]any{"value": 42}, &out)
fmt.Println(out["result"]) // 84
}
対象範囲 / 制限
- 同一ホスト/Podのみ(UDS)。Linux/macOSをサポート。Windowsの名前付きパイプは未対応です。
- リクエスト/レスポンスのペイロードが概ね ≲ ~100 KB のJSONに最適です。GPUオーケストレーションやホスト間サービングは対象外です。
ベンチマーク(目安)
- ローカルM1、シンプルなJSON: 8ワーカーで ~45µs p50、~200k req/s。実際の数値は環境により異なります。
含まれるもの
- Pure Goクライアント(CGOなし)、Pythonワーカーライブラリ、プール、ヘルスチェック、グレースフルリスタート、サンプル。
ドキュメントとコード
- README、設計/運用/セキュリティドキュメント、pkg.go.dev: https://github.com/YuminosukeSato/pyproc
ライセンス
- Apache-2.0。現行リリース: v0.2.x。
フィードバック歓迎
- APIの使いやすさ、高負荷時の障害モード、コーデック/トランスポートの優先順位(例: Arrow IPC、gRPC-over-UDS)。
まだコメントはありません。