Skip to main content

Run high-performance Mojo code from Python - three patterns for any environment

Project description

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.

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

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.

Supported by

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