Skip to main content

Simplify Python-Go integration for Libraries with Precompiled Extensions

Project description

Python Golang Tools

This project aims to bridge the gap between Python and Golang, enabling developers to easily create high performance Python libraries with precompiled Go extensions. pygo-tools wraps the setup function from setuptools and handles the process of compiling your library's golang source before building the wheel file. pygo-tools also patches the resulting extension, removing the need to manually configure LD_LIBRARY_PATH or DYLD_LIBRARY_PATH before runtime.

Installation

pip install pygo-tools

Example Projects

Walkthrough for Hello World with setup.py and config.json

Project Structure

|-- Makefile
|-- config.json
|-- example
|   |-- __init__.py
|   |-- go
|   |   |-- Makefile
|   |   `-- main.go
|   |-- lib -> go/local
|   `-- wrapper.py
|-- MANIFEST.in
|-- setup.py
`-- test.py

Project Config

pygo-tools looks for config.json at the root of your project. The config contains metadata like the python package name, golang library, python extension, and C functon signatures for the underlying library.

{
  "package": "example",
  "extension": "_example",
  "library": "hello",
  "signatures": [
    "char* Hello(char* message, int count);"
  ]
}

Go

// example/go/main.go

package main

import "C"
import "fmt"

func hello(message string, count int) string {
	return fmt.Sprintf("hello %s %d", message, count)
}

//export Hello
func Hello(message *C.char, count C.int) *C.char {
	result := hello(C.GoString(message), int(count))
	return C.CString(result)
}

func main() {}
# example/go/Makefile

all: clean build

build:
	go build -buildmode=c-shared -o local/libhello.so main.go

clean:
	@rm -rf local

Python

# example/wrapper.py

from _example import ffi, lib
from dataclasses import dataclass


@dataclass
class ExtensionAdapter:

    @staticmethod
    def hello(message: str, count: int = 1) -> str:
        params = ffi.new('char[]', message.encode()), ffi.cast('int', count)
        result = lib.Hello(*params)
        return ffi.string(result).decode()
# example/__init__.py
from .wrapper import ExtensionAdapter
# test.py

from example import ExtensionAdapter

adapter = ExtensionAdapter()
print(adapter.hello(message='world', count=4))
# setup.py

from pygo_tools import setup
from setuptools import find_packages

setup(
    name='example',
    version='0.1.0',
    packages=find_packages(),
    include_package_data=True
)
# MANIFEST.in
include example/go/*.go
include example/lib/*.so
all: clean build post_build

build:
	python -m build -n --wheel
	unzip -l dist/*.whl

clean:
	@rm -rf build dist *.egg-info
	@rm -rf */go/local

post_build:
	@rm -rf build *.egg-info

Build

The Makefile at the project level runs python -m build -n --wheel in order to create the wheel file under the dist folder. The binary distribution should include your python and golang source code, along with the compiled library and extension.

- example/lib/libhello.so
- _example.abi3.so

Testing

Install the wheel file in your virtual environment and run python test.py to check that things are working end to end locally.

Distributing

Binary distributions with compiled code should be built for each platform that you want to support during runtime. [cibuildwheel] can be used for this. However, you can also create a Dockerfile and docker-compose.yaml to build wheels for linux/arm64 and linux/amd64:

# Dockerfile
ARG PYTHON_VERSION=3.12
FROM public.ecr.aws/sam/build-python${PYTHON_VERSION}
RUN dnf install -y golang make
RUN pip install -U pip setuptools
RUN pip install pygo-tools
COPY example example/
COPY setup.py config.json MANIFEST.in ./
RUN python -m build -n --wheel
ENTRYPOINT ["/bin/sh"]
# docker-compose.yaml
version: '3'
services:
  builder:
    build: .
    platform: linux/arm64
    volumes:
      - ./out:/var/task/out:rw
    entrypoint: ["/bin/sh", "-c"]
    command: ["cp dist/* out/"]

Related Links

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pygo-tools-0.1.8.tar.gz (8.5 kB view details)

Uploaded Source

Built Distribution

pygo_tools-0.1.8-py3-none-any.whl (8.4 kB view details)

Uploaded Python 3

File details

Details for the file pygo-tools-0.1.8.tar.gz.

File metadata

  • Download URL: pygo-tools-0.1.8.tar.gz
  • Upload date:
  • Size: 8.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/5.0.0 CPython/3.10.0

File hashes

Hashes for pygo-tools-0.1.8.tar.gz
Algorithm Hash digest
SHA256 4707aaa145f4c1c60a683dba36e62b5999d761a4f9c0976d5a9899f0b8765b52
MD5 d825b7df220c048257fe11d6582ea98f
BLAKE2b-256 4d277ee0ca64577b9fe579261ed1e52b9a805c9767a7f590786a1c9887535386

See more details on using hashes here.

File details

Details for the file pygo_tools-0.1.8-py3-none-any.whl.

File metadata

  • Download URL: pygo_tools-0.1.8-py3-none-any.whl
  • Upload date:
  • Size: 8.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/5.0.0 CPython/3.10.0

File hashes

Hashes for pygo_tools-0.1.8-py3-none-any.whl
Algorithm Hash digest
SHA256 688bc2b95b8b107c8cfac5f10906f8769349f18e75dffaf746cf79b5e3cea968
MD5 7db2d1ac1562031ac33c47fa336f0c7f
BLAKE2b-256 54eca68df2df8b8cc02ce60d4573424bdf93dd0590ae5cad85dd6d4a4fe33b8e

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page