Skip to content

TimLai666/usegolib

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

75 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

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 in Python.

Resources

License

Security policy

Stars

Watchers

Forks

Packages

 
 
 

Contributors