7.0.1850-testing

Python library

GreyCat is often compared to Python, as both are programming languages.

However, GreyCat’s primary target is SQL, the de facto language for querying databases.

Unlike garbage-collected languages such as Python or JavaScript, GreyCat scales to billions of persisted data nodes without performance degradation.

That said, as a niche project, GreyCat lacks readily available libraries, particularly for emerging use cases like LLM integration.

Bindings help bridge this gap, but clear boundaries must be defined for each component’s responsibilities.

Component Interaction

GreyCat WebComponents JSGreyCat Server HTTP APIGreyCat Fn StatefulPython Fn Stateless

In Summary

We aim to enable stateless Python function calls from GreyCat code.

Usage

Add python library as any other native libraries using: greycat

@library("std", "7.0.1704-testing");
@library("python", "7.0.172-testing");

fn main(){
  pprint("py_runtime_version: ${Python::get_version()}");
}

The GreyCat Python library comes with a full python interpreter 3.12 embedded and not related to the one of the system

[root@dth4 v7py]# tree bin
bin
├── greycat
├── pip3
└── python3

Let’s simply run it and print the available version

[v7py]# ./bin/greycat run
py_runtime: 3.12.9 (main, Mar  6 2025, 00:44:11) [GCC 12.3.1 20230508 (Red Hat 12.3.1-1)]

Bind python function

native fn hi_python(v: String): String;

fn main(){
  pprint(hi_python("gc_py_lib"));
}

Then defines in a project.py

from greycat import gc_native

@gc_native("project::hi_python")
def hi_python(v: str) -> str:
    return f"Hello, {v}!"

Let’s simply run it

[v7py]# ./bin/greycat run
Hello, gc_py_lib!

Dependencies

To avoid known hell of python deps we have hard wired pip to install everything locally, the venv way

As classic pip requirements.txt is the sole source of definition for python deps

numpy==1.26.4
pandapower==3.0.0

Then install deps using the following commands:

./bin/pip3 install -r requirements.txt

Packages are installed in

./lib/python/lib/python3.12/site-packages

Now all pandapower functions are available in project.py


Codegen, GreyCat-side

type Person {
    name: String;
    birthday: time;
}

native fn get_persons(map: Map<String, time>): Array<Person>;

native fn map_persons(persons: Array<Person>): Map<String, time>;

fn main() {
  var map = Map<String, time>{};
    map.set("Doe", 0_time);
    map.set("Ada", time::parse("1815-12-10T00:00:00", null));
    var persons = get_persons(map);
    pprint(persons);
    pprint(map_persons(persons));
}

Generate Python bindings in current directory:

greycat codegen --target=python .

Codegen, Python-side

native fn get_persons(map: Map<String, time>): Array<Person>;
native fn map_persons(persons: Array<Person>): Map<String, time>;

Then in project.py:

from greycat_types import *

@gc_native("project::get_persons")
def get_persons(map: core.Map[str, core.time]) -> core.Array[project.Person]:
    persons: core.Array[project.Person] = core.Array.create()
    for name, birthday in map.items():
        persons.append(project.Person.create(name, birthday))
    return persons

@gc_native("project::map_persons")
def map_persons(persons: core.Array[project.Person]) -> core.Map[str, core.time]:
    map: core.Map[str, core.time] = core.Map.create()
    person: project.Person
    for person in persons:
        map[person.name()] = person.birthday()
    return map

Codegen, GreyThon (or PyCat, pick your poison)

$ greycat run
Array<Person> {
  Person {
    name: "Ada",
    birthday: '1815-12-10T00:00:00Z'
  },
  Person {
    name: "Doe",
    birthday: '1970-01-01T00:00:00Z'
  }
}
Map<String,time> {
  "Ada": '1815-12-10T00:00:00Z',
  "Doe": '1970-01-01T00:00:00Z'
}

Availability

  • mac arm64
  • linux x64
  • linux arm64
  • windows still under dev

Drawbacks

Python takes a very different approach internally compared to GreyCat:

  • Python uses a Global Interpreter Lock (GIL) (single-threaded, cooperative scheduler, released during math kernel execution)

  • GreyCat uses a share-nothing architecture (fully independent threaded execution, fusion happens at transaction commits)

Injecting Python functions introduces major performance bottlenecks and makes packaging tricky.

Thus, use it with caution! Python functions can become technical debt when it comes to scaling.

That said, prioritizing features and leveraging GreyCat aims to keep all web development and data models aligned.

Do we expect this to change?

We studied Python’s GIL, especially the sub-interpreter proposal in recent Python versions.

However, this impacts the wide variety of existing libraries—such as NumPy—which are effectively incompatible…

Python’s major strength, its library ecosystem, is also a major drawback, as upgrading them can take decades.