Rodrigo Girão Serrão: TIL #146 – Using maturin through uv

Wait 5 sec.

Today I learned how to setup a Rust project that can be called from Python with PyO3 and maturin through uv.When you follow the PyO3 getting started guide to create a simple Rust project that can be called from Python, the instructions you get assume you'll use a global Python installation to create a virtual environment and to install maturin into it.You can use uv through maturin, but if your project also has a Rust binary, things may break.When you run a command like cargo run, cargo will see the dependency on PyO3 and it will then look for a Python installation.If you have no global Python installations — because you do everything through uv — or if your global installations aren't setup exactly like a vanilla, default installation, PyO3 might fail.The fix is simple.In .cargo/config.toml add the environment variable PYO3_PYTHON that points to the Python inside your virtual environment:# .cargo/config.toml[env]PYO3_PYTHON = { value = ".venv/bin/python", relative = true }How to set up a Rust + Python project with PyO3 and maturin through uvHere are all the steps to set up a Rust project that can be compiled into a binary executable and that can also be used from within Python:% cargo new calculator% cd calculatorCreate the file lib.rs:// lib.rspub fn add(a: i32, b: i32) -> i32 { a + b}#[pyo3::pymodule]mod calculator { use pyo3::prelude::*; #[pyfunction] fn add(a: i32, b: i32) -> PyResult { Ok(crate::add(a, b)) }}And update the file main.rs to depend on your calculator:use calculator::add;fn main() { println!("{}", add(1, 2));}If you run cargo run, you should get the result 3:% cargo run3Add the PyO3 dependency from the Rust side:% cargo add pyo3 -F abi3-py38Update Cargo.toml to configure your crate type so it can be compiled for the Rust binary and for the Python bridge:# Cargo.toml# ...[lib]name = "calculator"crate-type = ["cdylib", "rlib"]Now, create a minimal pyproject.toml:# pyproject.toml[project]name = "calculator"version = "0.1.0"[build-system]requires = ["maturin>=1.0,