Cython quickstart: compile_and_load#
This example shows the minimal workflow:
Compile a small Cython snippet at runtime.
Call the compiled function immediately.
Inspect build/cache metadata (key, build dir, artifact path).
Demonstrate profiles, pin/alias, and restart-safe re-import by key.
Notes#
Runtime compilation requires:
a working C/C++ compiler toolchain
Python development headers (
Python.h)the
Cythonpackage(optional) NumPy if
numpy_support=Trueand your code uses NumPy C-API
If prerequisites are not available (common on doc builders), this example prints a short diagnostic and exits gracefully.
# Authors: The scikit-plots developers
# SPDX-License-Identifier: BSD-3-Clause
from __future__ import annotations
from scikitplot import cython
def _print_prereq_summary(report: dict) -> None:
"""Print a stable, user/dev friendly prereq summary."""
print("Prereq ok:", report.get("ok", False))
for k in ("cython", "setuptools", "numpy", "compiler", "python_headers"):
if k in report:
item = report.get(k, {})
if isinstance(item, dict):
ok = item.get("ok", False)
ver = item.get("version", None)
msg = item.get("message", None)
s = f" - {k}: ok={ok}"
if ver:
s += f", version={ver}"
if msg:
s += f", message={msg}"
print(s)
Basic environment diagnostic (safe to run on doc builders)
report = cython.check_build_prereqs()
_print_prereq_summary(report)
Prereq ok: False
- cython: ok=True, version=3.2.4
- setuptools: ok=True, version=79.0.1
Generate python Module from python#
if not report.get('cython', {}).get('ok'):
print("\nCython runtime compilation prerequisites are missing.")
# If your implementation provides a formatted string, prefer it.
fmt = getattr(report, "format", None)
if callable(fmt):
print(fmt())
else:
problems = report.get("problems", [])
if problems:
print("Problems:", problems)
else:
# ------------------------------------------------------------
# 1) Compile a tiny Cython function and call it immediately.
# ------------------------------------------------------------
code_f = "def f(int n):\n return n*n\n"
try:
m = cython.compile_and_load(code_f, profile="fast-debug")
except Exception as e:
# Docs-safe: show error without crashing the whole gallery build.
print("\nCompilation failed (showing exception and exiting gracefully):")
print(type(e).__name__ + ":", e)
else:
print("\nCompiled module name:", getattr(m, "__name__", "<unknown>"))
print("f(10) =", m.f(10))
# ------------------------------------------------------------
# 2) If you need build metadata, use *_result API.
# ------------------------------------------------------------
code_g = "def g(int n):\n return n+1\n"
r = cython.compile_and_load_result(
code_g,
profile="fast-debug",
numpy_support=True,
numpy_required=False,
)
print("\nBuildResult (metadata):")
print(" module_name :", r.module_name)
print(" cache key :", r.key)
print(" build dir :", r.build_dir)
print(" artifact :", r.artifact_path)
print(" used_cache :", r.used_cache)
print(" created_utc :", r.created_utc)
# Call g to prove the compiled module is live.
print("g(10) =", r.module.g(10))
# ------------------------------------------------------------
# 3) Restart-safe workflow: import again by cache key.
# ------------------------------------------------------------
# This simulates "after kernel restart" behavior.
try:
m2 = cython.import_cached(r.key)
except Exception as e:
print("\nCould not re-import from cache by key:")
print(type(e).__name__ + ":", e)
else:
print("\nRe-imported from cache key:")
print(" module:", m2.__name__)
print(" g(10) :", m2.g(10))
# ------------------------------------------------------------
# 4) Pin/Alias for friendly reuse.
# ------------------------------------------------------------
alias = "quickstart_g"
try:
cython.pin(r.key, alias=alias, overwrite=True)
m3 = cython.import_pinned(alias)
except Exception as e:
print("\nPin/import by alias failed:")
print(type(e).__name__ + ":", e)
else:
print("\nImported via alias:", alias)
print(" module:", m3.__name__)
print(" g(10) :", m3.g(10))
# ------------------------------------------------------------
# 5) Profile demonstration: release build gets a different key.
# ------------------------------------------------------------
r_rel = cython.compile_and_load_result(code_g, profile="release", numpy_support=True, numpy_required=False)
print("\nProfile comparison (keys):")
print(" fast-debug:", r.key)
print(" release :", r_rel.key)
print(" keys differ:", r.key != r_rel.key)
# Optional: print cache stats snapshot, if available.
if hasattr(cython, "cache_stats"):
print("\nCache stats snapshot:")
print(cython.cache_stats())
Compiled module name: scikitplot_cython_c71820fcbdd3d3be
f(10) = 100
BuildResult (metadata):
module_name : scikitplot_cython_093729e666d9308a
cache key : 093729e666d9308a2ee01f667576da3e7022aaf802855405f2fe6727629b9a2a
build dir : /home/circleci/.cache/scikitplot/cython/093729e666d9308a2ee01f667576da3e7022aaf802855405f2fe6727629b9a2a
artifact : /home/circleci/.cache/scikitplot/cython/093729e666d9308a2ee01f667576da3e7022aaf802855405f2fe6727629b9a2a/scikitplot_cython_093729e666d9308a.cpython-311-x86_64-linux-gnu.so
used_cache : False
created_utc : 2026-02-01T06:33:52Z
g(10) = 11
Re-imported from cache key:
module: scikitplot_cython_093729e666d9308a
g(10) : 11
Imported via alias: quickstart_g
module: scikitplot_cython_093729e666d9308a
g(10) : 11
Profile comparison (keys):
fast-debug: 093729e666d9308a2ee01f667576da3e7022aaf802855405f2fe6727629b9a2a
release : 106892295832cfc7f01dbb65bd06b364352040aef37075f2634c508019b279d1
keys differ: True
Cache stats snapshot:
CacheStats(cache_root=PosixPath('/home/circleci/.cache/scikitplot/cython'), n_modules=5, n_packages=0, total_bytes=2935681, pinned_aliases=1, pinned_keys=1, newest_mtime_utc='2026-02-01T06:33:53Z', oldest_mtime_utc='2026-02-01T06:33:52Z')
Total running time of the script: (0 minutes 2.544 seconds)
Related examples