{"id":9099,"library":"maturin-import-hook","title":"Maturin Import Hook","description":"The maturin-import-hook library provides a Python import hook for projects built with `maturin`, allowing Python code to dynamically load and use Rust modules without needing an `editable` install or pre-building. It simplifies development workflows for mixed Python/Rust projects by building the Rust extension on demand. The current version is 0.3.0, and it generally follows a bug-fix driven release cadence with support for new Python versions.","status":"active","version":"0.3.0","language":"en","source_language":"en","source_url":"https://github.com/PyO3/maturin-import-hook.git","tags":["python","rust","maturin","import-hook","build-system","development-workflow","pyo3"],"install":[{"cmd":"pip install maturin-import-hook","lang":"bash","label":"Install maturin-import-hook"},{"cmd":"pip install maturin","lang":"bash","label":"Install maturin (required dependency)"}],"dependencies":[{"reason":"Required for building and locating Rust extensions.","package":"maturin","optional":false}],"imports":[{"symbol":"install","correct":"import maturin_import_hook; maturin_import_hook.install()"}],"quickstart":{"code":"import maturin_import_hook\nimport sys\nimport os\nimport shutil\n\n# This hook allows Python to find and load Rust modules\n# defined in a maturin project within the current directory\n# or a parent directory.\nmaturin_import_hook.install()\n\n# --- Setup a dummy Rust project for demonstration ---\n# In a real project, this setup would already exist.\nproject_name = \"my_rust_module\"\nproject_dir = \"temp_rust_project\"\nmodule_path = os.path.join(project_dir, \"src\")\n\n# Clean up any previous run's artifacts\nif os.path.exists(project_dir):\n    shutil.rmtree(project_dir)\n\nos.makedirs(module_path, exist_ok=True)\n\n# Create pyproject.toml\nwith open(os.path.join(project_dir, \"pyproject.toml\"), \"w\") as f:\n    f.write(f\"\"\"\n[project]\nname = \"{project_name}\"\nversion = \"0.1.0\"\n\n[tool.maturin]\nname = \"{project_name}\"\nbindings = \"pyo3\"\n    \"\"\")\n\n# Create Cargo.toml (maturin can infer some parts, but explicit is clearer for quickstart)\nwith open(os.path.join(project_dir, \"Cargo.toml\"), \"w\") as f:\n    f.write(f\"\"\"\n[package]\nname = \"{project_name}\"\nversion = \"0.1.0\"\nedition = \"2021\"\n\n[lib]\nname = \"{project_name}\"\ncrate-type = [\"cdylib\"]\n\n[dependencies]\npyo3 = {{ version = \"0.20\", features = [\"extension-module\"] }}\n    \"\"\")\n\n\n# Create src/lib.rs with a simple PyO3 function\nwith open(os.path.join(module_path, \"lib.rs\"), \"w\") as f:\n    f.write(\"\"\"\nuse pyo3::prelude::*;\n\n#[pyfunction]\nfn greet() -> PyResult<String> {\n    Ok(\"Hello from Rust!\".to_string())\n}\n\n#[pymodule]\nfn my_rust_module(_py: Python<'_>, m: &PyModule) -> PyResult<()> {\n    m.add_function(wrap_pyfunction!(greet, m)?)?;\n    Ok(())\n}\n        \"\"\")\n\n# Change to the project directory so the hook can find pyproject.toml\noriginal_cwd = os.getcwd()\nos.chdir(project_dir)\n\nprint(f\"Attempting to import '{project_name}' from: {os.getcwd()}\")\n\n# Now, import the Rust module as if it were a Python module\n# The hook will find pyproject.toml and potentially build the module.\ntry:\n    import my_rust_module\n    message = my_rust_module.greet()\n    print(f\"✅ Successfully imported and called Rust module: {message}\")\nexcept ImportError as e:\n    print(f\"❌ Failed to import Rust module: {e}\", file=sys.stderr)\n    print(\"Ensure 'maturin' is installed (pip install maturin) and your Rust project is valid.\", file=sys.stderr)\nexcept Exception as e:\n    print(f\"❌ An unexpected error occurred: {e}\", file=sys.stderr)\nfinally:\n    # Clean up dummy project and restore original cwd\n    os.chdir(original_cwd)\n    if os.path.exists(project_dir):\n        print(f\"Cleaning up temporary project directory: {project_dir}\")\n        shutil.rmtree(project_dir)\n","lang":"python","description":"Demonstrates how to use `maturin-import-hook` to dynamically load a Rust module defined in a `maturin` project. It sets up a minimal Rust project with a `pyproject.toml` and `src/lib.rs`, installs the hook, imports the Rust module, calls a function, and then cleans up. This example assumes `maturin` is already installed in your environment."},"warnings":[{"fix":"Install `maturin` using `pip install maturin` in the same environment where you are using `maturin-import-hook`.","message":"The `maturin` CLI tool must be installed in the active Python environment for the import hook to function. It is a runtime dependency used by the hook to locate and potentially build Rust extensions.","severity":"gotcha","affected_versions":"All versions"},{"fix":"Ensure your Python script is run from within your `maturin` project directory, or a subdirectory where `pyproject.toml` is in an ancestor directory.","message":"The import hook relies on finding a `pyproject.toml` file in the current working directory or a parent directory to identify the Rust project root. If the file is not discoverable, the hook will fail to find or build your Rust module.","severity":"gotcha","affected_versions":"All versions"},{"fix":"Be aware of this initial build time in development. In production, pre-building and packaging your Rust extensions (e.g., using `maturin build --release`) is generally recommended.","message":"The first time a Rust module is imported via the hook (or if the built artifact is missing/outdated), it will trigger a full `maturin build` process. This can introduce significant latency to the initial import, especially for large Rust projects.","severity":"gotcha","affected_versions":"All versions"},{"fix":"Call `maturin_import_hook.install()` early in your application's startup. Test thoroughly if combining with other advanced import system modifications.","message":"The import hook modifies `sys.meta_path`. If your application uses other import hooks or heavily manipulates `sys.meta_path`, there's a potential for conflicts or unexpected behavior.","severity":"gotcha","affected_versions":"All versions"}],"env_vars":null,"last_verified":"2026-04-16T00:00:00.000Z","next_check":"2026-07-15T00:00:00.000Z","problems":[{"fix":"Ensure `maturin_import_hook.install()` is called early in your application's lifecycle, and verify that a valid `pyproject.toml` file is in the current working directory or a parent relative to where the script is run.","cause":"The `maturin_import_hook.install()` function was not called, or the `pyproject.toml` and Rust project structure are not correctly set up or discoverable by the hook.","error":"ImportError: No module named 'your_rust_module'"},{"fix":"Install `maturin` using `pip install maturin` in the same Python environment.","cause":"The `maturin` CLI tool, which `maturin-import-hook` relies on for building and discovery, is not installed in the active Python environment.","error":"ModuleNotFoundError: No module named 'maturin'"},{"fix":"Review the detailed error messages from `cargo build` (which `maturin` wraps) to diagnose and fix issues in your `Cargo.toml` or Rust source code. You can often reproduce these by running `maturin build` manually in your Rust project directory to get clearer output.","cause":"The underlying Rust project has compilation issues (e.g., syntax errors, missing dependencies in `Cargo.toml`, incorrect PyO3 bindings). These errors occur when the hook attempts to build the Rust extension.","error":"(Rust compiler errors, e.g., 'error[E0425]: cannot find function `some_rust_function` in crate `some_crate`' during import)"}]}