Rust-powered Python tools: uv, Ruff and Polars
Rust-powered Python tools solve different problems: uv manages project environments and dependencies, Ruff lints and formats Python source, and Polars processes dataframe workloads. Choose the layer causing friction first. You can use these tools together or independently; adopting a tool written in Rust does not turn your Python application into Rust.
By Built with Rust editorial · Published
A new Python project can start with all three, but an existing project does not need to migrate all three layers at once. This guide compares their jobs, the changes each introduces, and a small trial you can use to decide whether to keep it. The examples come from the Built with Rust catalog; this is a selection guide, not a benchmark or a ranking of every Python tool.
Choose the job, not the implementation language
Start by naming the work you want to improve. Recreating an environment, reviewing lint failures and running a data transformation are separate tasks. A tool can improve one without affecting the others. If your application spends its time waiting for an external service, changing its formatter is not a runtime optimization. Keep the question narrow enough that you can check the result.
Scroll the table sideways to see the trial checks.
| Your problem | Try | Leave unchanged | Check before keeping it |
|---|---|---|---|
| Environment setup is awkward | uv: recreate one project environment | Application code, lint rules and dataframe library | Dependencies resolve; tests and CI still run |
| Code checks are slow or fragmented | Ruff: inspect lint and formatting reports | Package manager, type checker and runtime code | Required rules are covered; formatting diffs are acceptable |
| A data transformation needs attention | Polars: port one representative transformation | Unrelated pipelines and development tooling | Outputs match; time and memory suit the workload |
uv: change how the project environment is managed
uv is Astral’s Python package and project manager, written in Rust. It manages dependencies, virtual environments and Python versions. It can also install and run packaged command-line tools. That puts it around your application: it prepares the environment in which Python runs. See the official uv overview for its supported workflows.
In uv’s project workflow, pyproject.toml describes the project and its requirements, uv.lock records resolved dependencies, and a project environment holds installed packages. The project guide explains how these pieces work together. This is distinct from using uv’s pip interface to manage an existing environment. Choose the workflow deliberately instead of mixing instructions from both and assuming they maintain the same project state.
For an existing repository, trial uv on a branch and in a fresh environment. Confirm the Python version, dependency sources and test command before comparing setup times. Check private package indexes and CI explicitly: uv’s pip compatibility documentation describes differences from pip, including configuration handling. Keep the current workflow if a required integration does not yet work or the change costs more than the problem it solves. You can evaluate Ruff without changing package managers.
Ruff: change feedback on Python source
Ruff is a Python linter and formatter written in Rust. Linting reports selected code-quality issues; formatting applies a consistent layout. Neither job resolves the application’s dependencies or executes its dataframe queries. The Ruff overview describes the two capabilities, which you can adopt separately.
Begin with reports, not an automatic rewrite. Check existing editor, hook and auto-fix settings first. Inventory the lint rules your team relies on, compare their coverage, and inspect proposed changes on a branch. Ruff distinguishes safe and unsafe fixes; that distinction matters when deciding which changes to automate. Its linter documentation is the source for rule selection and fix behavior. A cleaner report is not enough if an important check disappeared during migration.
Treat formatting as a separate decision. Ruff aims for compatibility with Black’s style but documents intentional differences, and its maintainers discourage alternating the two formatters on the same codebase. Review a formatting-only diff before combining it with a functional change. Read the formatter documentation and retain your type checker: Ruff is not a type checker. Keep running existing tests and add focused checks for changed behavior.
Polars: change the dataframe work itself
Polars is a dataframe library with a Rust core and a Python interface. Unlike uv and Ruff, it can be part of the code that processes your application’s data. Its user guide introduces expressions for operations such as selecting, filtering and aggregating columns. Choose it because that model fits a data task, not because every project should have a Rust-based library.
Polars supports eager work and lazy query plans. Lazy execution lets the engine optimize a plan before running it; the lazy API guide explains that distinction. This is not a promise that every workload becomes faster or fits in memory. If the real bottleneck is a Python callback, review whether a native expression can represent the operation. The user-defined function guide explains callback tradeoffs; custom Python functions can still be useful.
A pandas migration is more than changing an import. Polars has different API and type semantics and no pandas-style row index. Use the official pandas migration guide to plan a trial. Port one representative transformation, then compare values, null handling, data types, joins and output ordering where your application relies on them. Retain pandas when the existing pipeline meets your needs or downstream integrations make the migration unjustified. Adopting uv or Ruff does not require this rewrite.
Make the first change small enough to judge
Use the table as a worksheet, not an instruction to install everything. Write down one current frustration and the result that would justify a switch. For environment management, that might be a reliable fresh setup in CI. For source checks, it might be shorter feedback while retaining required rules. For a data pipeline, it might be meeting a runtime or memory limit without changing the result. These are proposed acceptance checks, not improvements measured by this directory.
- Record the working baseline. Keep the current dependency files and configuration in version control. Record the command or process you are replacing and the inputs it uses.
- Change one layer on a branch. Avoid a package-manager migration, a repository-wide formatting diff and a dataframe rewrite in the same review. Separate changes make surprises easier to trace and reverse.
- Check correctness before speed. Run the existing tests, inspect source changes and compare data outputs. Add a focused check where the current suite does not cover the behavior you are changing.
- Measure the relevant task. Compare equivalent inputs and record tool versions, hardware and cache state. A warm installation and a cold installation answer different questions; neither is an application runtime benchmark.
- Keep or stop explicitly. Adopt the change if it meets the agreed check. Otherwise keep the working setup and record the incompatibility or missing benefit, rather than migrating the next layer to justify the first.
For a new project, the same boundaries still help. Decide whether you need dataframe processing at all before choosing Polars. Then choose environment management and source checks on their own merits. A small service can use uv and Ruff without Polars; a data application can use Polars with its existing tools. There is no combined speed multiplier to calculate from three benchmarks that measure different jobs.
Common selection questions
Can I use uv, Ruff and Polars together?
Yes. uv manages the Python project environment, Ruff checks and formats Python source, and Polars handles dataframe operations. You can also adopt each independently.
Does Ruff replace a type checker?
No. Ruff is a linter and formatter, not a type checker. Keep type checking and tests as separate parts of your workflow.
Is Polars a drop-in replacement for pandas?
No. Polars has a different API and execution model, including expressions and no pandas-style row index. Migrate and validate a representative transformation before expanding its use.
Explore the tool for your next change
Open the uv listing, Ruff listing or Polars listing for its website and source repository. For adjacent tasks, browse Rust-built developer tools and data and AI projects. Check current installation requirements upstream before switching.
Scope: selected catalog projects, checked against their official documentation on October 10, 2026. The trial checklist is Built with Rust’s editorial recommendation, not a vendor benchmark. Directory star counts are stored snapshots, not live totals.