Skip to content
TimLai666Public

About

Call Go libraries from Python by loading a Go-built shared library directly into the Python process.

Topics

Resources

Security policy

Stars

1 star

Watchers

0 watching

Forks

Latest commit

 

History

75 Commits

Folders and files

Repository files navigation

usegolib

CI PyPI Python Versions License

Call Go libraries from Python by loading a Go-built shared library directly into the Python process.

  • No C/C++ glue code written by you
  • No background Go process (no daemon / RPC / subprocess)
  • MessagePack-based ABI with manifest-driven schema validation

Status

usegolib is early-stage software (v0.x). Expect sharp edges and evolving interfaces.

How It Works

  • Build time (CI / build machine): use the Go toolchain plus an auto-provisioned C compiler (Zig) to build a Go module into a shared library and emit manifest.json.
  • Runtime (end-user / production): Python loads the shared library and calls it via MessagePack. No daemon, no RPC, no subprocess.

Requirements

  • Python 3.10+
  • Go toolchain
    • required for building artifacts (CI / build machine)
    • required in dev if you rely on auto-build (missing artifact triggers a build)
    • not required for end-user runtime if you ship prebuilt artifacts or wheels

Installation

python -m pip install usegolib

From source (dev):

python -m pip install -e ".[dev]"

Quickstart

Build an artifact from a local Go module directory:

usegolib build --module path/to/go/module --out out/artifact

Import from the artifact root and call exported functions:

import usegolib

h = usegolib.import_("example.com/mod", artifact_dir="out/artifact")
print(h.AddInt(1, 2))

Dev convenience: omit artifact_dir to use the default artifact cache root. If the artifact is missing, usegolib.import_ will build it into the default cache when a Go toolchain is available.

import usegolib

h = usegolib.import_("example.com/mod")
print(h.AddInt(1, 2))

To enforce "no build" behavior, pass an explicit artifact root and set build_if_missing=False:

import usegolib

h = usegolib.import_("example.com/mod", artifact_dir="out/artifact", build_if_missing=False)

Example: Calling Insyra From Python

Insyra is a Go data-analysis library: github.com/HazelnutParadise/insyra.

Auto-build on import (developer convenience; downloads the module + builds into usegolib's default artifact root):

import usegolib

insyra = usegolib.import_("github.com/HazelnutParadise/insyra", version="v0.2.14")

# DataList (object handle + variadic any)
dl = insyra.NewDataList()
dl.Append(1, 2, 3, 4, 5)
print(dl.Sum(), dl.Mean())

# DataTable (variadic map[string]any + variadic bool)
dt = insyra.NewDataTable()
dt.AppendRowsByColIndex({"A": 1, "B": 2}, {"A": 3, "B": 4})
print(dt.NumRows(), dt.NumCols())
dt.Show()

Notes:

  • usegolib can only call functions/methods whose parameter and return types are supported by the current type bridge (see docs/abi.md).
  • This example requires a Go toolchain to be installed. (At the time of writing, insyra@v0.2.14 requires go >= 1.25 and may cause Go to auto-download a newer toolchain.)
  • If you want to disable auto-build, pass build_if_missing=False (and usually an explicit artifact_dir).
  • For end-users without Go, ship prebuilt artifacts/wheels (see Packaging).

Methods (Object Handles)

For exported methods, usegolib supports Go-side object handles (opaque ids) to avoid serializing the receiver on every call:

with h.object("Counter", {"n": 1}) as c:
    print(c.Inc(2))

Typed object handles (schema required):

th = h.typed()
types = th.types

with th.object("Counter", types.Counter(N=10)) as c:
    snap = c.Snapshot()
    print(snap)

Generic Functions (Build-Time Instantiation)

Generic functions require explicit build-time instantiation:

usegolib build --module example.com/mod --out out/artifact --generics generics.json

At runtime (schema required), use the helper:

fn = h.generic("Id", ["int64"])
print(fn(123))

Packaging (Ship Wheels Without Requiring Go)

Generate a distributable Python package project embedding artifacts:

usegolib package --module path/to/go/module --python-package-name mypkg --out out/

Install the generated project:

python -m pip install -e out/mypkg
import mypkg

print(mypkg.AddInt(1, 2))

Version Rules

  • One Go module = one version per Python process
  • If a module is already loaded, all subpackages must use the same version
  • If version=None and multiple artifact versions exist under artifact_dir, import fails with AmbiguousArtifactError (unless that module is already loaded in the current process, in which case version=None follows the already-loaded version)

Documentation

  • docs/roadmap.md
  • docs/abi.md
  • docs/cli.md
  • docs/versioning.md
  • docs/compatibility.md
  • docs/testing.md
  • docs/security.md
  • docs/troubleshooting.md
  • docs/releasing.md

License

MIT. See LICENSE.

About

Call Go libraries from Python by loading a Go-built shared library directly into the Python process.

Topics

Resources

Security policy

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages