Skip to main content

py-run-mojo ๐Ÿ”ฅ

Notebook-agnostic Mojo integration for Python - three patterns for running high-performance Mojo code from any Python environment.

Status: โœ… Beta - Three working approaches, evolving based on real-world usage

Note: This library works with any Python notebook system (Jupyter, marimo, VSCode, Google Colab) and even standalone Python scripts. It was previously called mojo-marimo; the new name reflects its notebook-agnostic scopeโ€”see ROADMAP.md.

Overview

py-run-mojo (formerly mojo-marimo) provides three distinct patterns for executing Mojo code from Python, each with different trade-offs:

  1. Decorator (@mojo) - Clean Pythonic syntax with template parameters and caching
  2. Executor (run_mojo()) - Dynamic execution from strings or files, great for code generation
  3. Extension Module - Compiled .so files for zero-overhead FFI calls (~1000ร— faster than subprocess)

Works everywhere: Jupyter notebooks, marimo, VSCode notebooks, Google Colab, IPython REPL, or standalone Python scripts. The core library has no notebook-specific dependencies.

from py_run_mojo import mojo

@mojo
def fibonacci(n: int) -> int:
    """
    fn fibonacci(n: Int) -> Int:
        if n <= 1:
            return n
        var prev: Int = 0
        var curr: Int = 1
        for _ in range(2, n + 1):
            var next_val = prev + curr
            prev = curr
            curr = next_val
        return curr
    
    fn main():
        print(fibonacci({{n}}))
    """
    pass

# Use like normal Python!
result = fibonacci(10)

Why This Exists

Python notebooks are brilliant for exploration, but hit a wall when you need serious performance. Traditional solutionsโ€”rewriting in C/C++, using Numba/JAX, or pure Python optimisationโ€”are either too complex or don't deliver the 10-100ร— speedup you need.

The question: What if you could write high-performance Mojo code and run it interactively from Python notebooks with minimal friction?

This matters for:

  • Data scientists exploring algorithms that need real performance
  • Quant developers prototyping trading strategies or risk models
  • ML engineers benchmarking preprocessing pipelines or custom operators
  • Educators teaching performance engineering with immediate visual feedback

Features

Current (v0.1.0)

  • Three integration patterns (decorator, executor, extension modules)
  • Works with any Python environment (Jupyter, marimo, VSCode, IPython, scripts)
  • Interactive example notebooks in marimo and Jupyter (.ipynb) formats
  • SHA256-based binary caching (~/.mojo_cache/binaries/)
  • Pre-compilation validation (catches common syntax errors)
  • Cache management utilities (clear_cache(), cache_stats())
  • Monte Carlo and Mandelbrot examples with visualisation
  • 44 passing tests (75% coverage)
  • Comprehensive documentation + roadmap

Planned

See ROADMAP.md for full details:

  • Validate Jupyter compatibility with real-world testing
  • Auto-generate extension module boilerplate
  • Pattern library for common algorithms
  • Enhanced error handling and debugging
  • Multiple Mojo version support
  • Potential package rename (community feedback requested)

Installation

py-run-mojo supports both uv (recommended) and pixi for environment management.

Prerequisites

None! Mojo is now installed automatically as a Python package dependency.

Option 1: uv (Recommended)

# Clone the repository
git clone https://github.com/databooth/py-run-mojo
cd py-run-mojo

# Install dependencies (includes mojo)
uv sync --extra dev

# Verify setup
uv run python scripts/verify_setup.py

# Launch example notebook
uv run marimo edit notebooks/example_notebook.py

Option 2: pixi

# Clone the repository
git clone https://github.com/databooth/py-run-mojo
cd py-run-mojo

# Install with pixi
pixi install

# Verify setup
pixi run test-setup

# Launch example notebook
pixi run notebook-example

Quick Start

Pattern 1: Decorator (Recommended)

from py_run_mojo import mojo

@mojo
def sum_squares(n: int) -> int:
    """
    fn sum_squares(n: Int) -> Int:
        var total: Int = 0
        for i in range(1, n + 1):
            total += i * i
        return total
    
    fn main():
        print(sum_squares({{n}}))
    """
    pass

# Use like normal Python!
result = sum_squares(10)  # First call: ~1-2s, subsequent: ~10-50ms
print(result)  # 385

Pattern 2: Executor

from py_run_mojo import run_mojo

mojo_code = """
fn compute(n: Int) -> Int:
    return n * n

fn main():
    print(compute(42))
"""

result = run_mojo(mojo_code)  # Or run_mojo("path/to/file.mojo")
print(result)  # "1764"

Pattern 3: Extension Module

import mojo.importer  # Enables auto-compilation of .mojo โ†’ .so
import monte_carlo_mojo_ext

# Direct FFI call - no subprocess overhead!
x, y, inside, pi_est, error = monte_carlo_mojo_ext.generate_samples(1_000_000)
print(f"ฯ€ โ‰ˆ {pi_est:.6f} ยฑ {error:.6f}")

See examples/ and notebooks/ for complete working examples.

Usage

Verify Setup

# Using just
just test-setup

# Using uv
uv run python scripts/verify_setup.py

# Using pixi
pixi run test-setup

This checks that mojo is available and tests both approaches.

Interactive Notebooks

# Using just
just notebook-decorator  # @mojo decorator examples
just notebook-executor   # run_mojo() examples
just benchmark          # Performance comparison

# Using uv
uv run marimo edit notebooks/pattern_decorator.py
uv run marimo edit notebooks/pattern_executor.py
uv run marimo edit notebooks/benchmark.py

# Using pixi
pixi run notebook-decorator
pixi run notebook-executor
pixi run benchmark

Command-Line Demos

# Using just
just demo-examples
just demo-decorator

# Using uv
uv run python examples/examples.py
uv run python -m py_run_mojo.decorator

# Using pixi
pixi run demo-examples
pixi run demo-decorator

Performance Comparison

Testing on Apple Silicon (M-series) with fibonacci(10), sum_squares(100), and is_prime(104729):

Approach First Call Subsequent Calls Use Case
Uncached ~50-200ms ~50-200ms Development, debugging
Cached ~1-2s ~10-50ms Repeated execution
Decorator ~1-2s ~10-50ms Production, clean code

Key insights:

  1. Caching wins for repeated calls: 5-10ร— faster after first compilation
  2. Decorator has zero performance cost: Same speed as explicit caching, better developer experience
  3. All approaches deliver real Mojo performance: No Python fallbacks or compromises

See the benchmark notebook for detailed comparisons.

Documentation

Project Documentation

Blog & Announcements

Project Structure

py-run-mojo/
โ”œโ”€โ”€ src/
โ”‚   โ””โ”€โ”€ py_run_mojo/          # Core library
โ”‚       โ”œโ”€โ”€ executor.py       # Cached Mojo execution
โ”‚       โ”œโ”€โ”€ decorator.py      # @mojo decorator
โ”‚       โ”œโ”€โ”€ validator.py      # Pre-compilation validation
โ”‚       โ””โ”€โ”€ __init__.py       # Package exports
โ”œโ”€โ”€ examples/                 # Example implementations
โ”‚   โ”œโ”€โ”€ examples.py          # Python wrappers (fibonacci, etc.)
โ”‚   โ”œโ”€โ”€ examples.mojo        # Standalone Mojo code
โ”‚   โ””โ”€โ”€ reference/           # Reference .mojo files
โ”œโ”€โ”€ benchmarks/              # Performance benchmarking
โ”‚   โ”œโ”€โ”€ python_baseline.py   # Pure Python implementations
โ”‚   โ”œโ”€โ”€ mojo_implementations.py  # Mojo implementations
โ”‚   โ”œโ”€โ”€ python_vs_mojo.py    # Python vs Mojo comparison notebook
โ”‚   โ””โ”€โ”€ execution_approaches.py  # Execution patterns comparison
โ”œโ”€โ”€ notebooks/               # Interactive marimo notebooks
โ”‚   โ”œโ”€โ”€ pattern_decorator.py # @mojo decorator examples
โ”‚   โ”œโ”€โ”€ pattern_executor.py  # run_mojo() examples
โ”‚   โ”œโ”€โ”€ interactive_learning.py  # Learning notebook
โ”‚   โ””โ”€โ”€ gpu_puzzles/         # marimo notebooks scaffolding Mojo GPU Puzzles
โ”œโ”€โ”€ scripts/                 # Utility scripts
โ”‚   โ””โ”€โ”€ verify_setup.py      # Setup verification
โ”œโ”€โ”€ tests/                   # Test suite
โ”œโ”€โ”€ docs/                    # Documentation
โ”‚   โ”œโ”€โ”€ project/            # Project docs (contributing, changelog)
โ”‚   โ”œโ”€โ”€ blog_post_draft.md  # Blog post
โ”‚   โ”œโ”€โ”€ COMPILED_LANGUAGES.md  # Compiled language integration
โ”‚   โ”œโ”€โ”€ MODULAR_FORUM_ANNOUNCEMENT.md
โ”‚   โ””โ”€โ”€ MARIMO_ANNOUNCEMENT.md
โ””โ”€โ”€ README.md                # This file

Development

Using just (Recommended)

We provide a justfile with common tasks synced across uv and pixi:

# Show all available commands
just --list

# Install dependencies
just install

# Run tests
just test
just test-coverage

# Code quality
just format
just lint
just typecheck
just check              # Run all quality checks

# Notebooks
just notebook-decorator
just notebook-executor
just benchmark

# Development
just clean
just clean-mojo-cache
just cache-stats

# CI checks locally
just ci

Using uv

# Install in development mode
uv sync --extra dev

# Run tests
uv run pytest tests/

# Format code
uv run ruff format .

# Lint
uv run ruff check .

# Type check
uv run ty check

Using pixi

# Run tests
pixi run test

# Format code
pixi run format

# Lint
pixi run lint

# Type check
pixi run typecheck

# All quality checks
pixi run check

Why marimo?

marimo is a reactive Python notebook with several advantages:

  • Reactive execution: Change a slider, Mojo re-runs automatically
  • Pure Python files: Version control friendly (unlike Jupyter JSON)
  • Type-safe: Built-in UI elements with proper types
  • Reproducible: Dependency graph prevents hidden state bugs

Contributing

Contributions welcome! This is a living experiment, evolving based on real-world usage.

Areas for contribution:

  • Additional notebook examples
  • Performance profiling on diverse hardware
  • Integration with other notebook environments
  • Error handling improvements
  • Documentation enhancements

Related Projects

License

Apache License 2.0 - See LICENSE for details.

About

Created by Michael Booth at DataBooth.

Part of an ongoing exploration of Mojo for real-world data and AI workflows. See the full series at databooth.com.au/posts/mojo.

DataBooth helps medium-sized businesses leverage high-performance computing for data analytics and AI, now offering Mojo-powered services that deliver 10-100ร— faster solutions without vendor lock-in.

Download files

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

Source Distribution

py_run_mojo-0.1.3.tar.gz (193.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

py_run_mojo-0.1.3-py3-none-any.whl (17.4 kB view details)

Uploaded Python 3

File details

Details for the file py_run_mojo-0.1.3.tar.gz.

File metadata

  • Download URL: py_run_mojo-0.1.3.tar.gz
  • Upload date:
  • Size: 193.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: Hatch/1.16.3 cpython/3.14.0 HTTPX/0.28.1

File hashes

Hashes for py_run_mojo-0.1.3.tar.gz
Algorithm Hash digest
SHA256 438dd39a799d64603ed6416c6ffa0d2fc56010ee7577af5bd8109e1630feca3f
MD5 99794a0a53dc4e8eba88a57d7d52eb6c
BLAKE2b-256 4681b95393c5819a4bf150962f2125a706f6ec2cd53454f5944abf7502013ca9

See more details on using hashes here.

File details

Details for the file py_run_mojo-0.1.3-py3-none-any.whl.

File metadata

  • Download URL: py_run_mojo-0.1.3-py3-none-any.whl
  • Upload date:
  • Size: 17.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: Hatch/1.16.3 cpython/3.14.0 HTTPX/0.28.1

File hashes

Hashes for py_run_mojo-0.1.3-py3-none-any.whl
Algorithm Hash digest
SHA256 69ee3b0c949c741f8254448b92fc2d2d7e5a103edb31e8e4c3f737c3c105f11e
MD5 a62ee3730599952912bbada48a0b2ef8
BLAKE2b-256 5429fdeef561e98c8d048f2fd6939ee9ec796784635f5531ca9692e9e44ccff4

See more details on using hashes here.

Release history Release notifications | RSS feed

This release

0.1.3 This release

2 files

0.1.2

2 files

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page