Astral is good: ruff


Python has not been great for tooling. Compared to Rust, Go, and Terraform. Python tooling (flake8, black, isort, mypy, etc.) is clunky and poorly integrated. Before Maintaining a Python project means juggling multiple tools with overlapping responsibilities and conflicting opinions about your code.

Ruff changes this.

What is Ruff?

Ruff is a Python linter and formatter written in Rust. It's ridiculously fast. It replaces flake8, black, isort, pyupgrade, autoflake, and several other tools with a single binary that runs in milliseconds instead of seconds.

# Before Ruff
black src/   # 1.8s

# With Ruff
ruff format src/ # 0.01s
The Good
Speed

Ruff is absurdly fast. What used to take 5+ seconds in my CI pipeline now takes under 40ms. This isn't just nice-to-have—it fundamentally changes how I work. You can run formatting and linting on every save without thinking twice.

Consolidation

One tool, one config file, one set of rules. No more wrestling with conflicting opinions between black and flake8 about line length, or debugging why isort and black disagree about import ordering. If only prettier and eslint cooperated as well.

Drop-in replacement

Ruff implements the same rules as the tools it replaces. My existing pyproject.toml configurations work mostly work as-is.

The Limitations
Rust dependency

If you're in a pure Python environment where adding Rust tooling raises eyebrows, this could be a concern. Though honestly, most Python developers already have Rust tooling somewhere in their stack.

Newer ecosystem

While Ruff has excellent compatibility with existing tools, it's still evolving. Some edge cases that worked in the old tools might behave differently. In practice, I've encountered this exactly zero times.

The Reality

I've been using Ruff in production for over a year. It's replaced my entire linting and formatting pipeline. My pyproject.toml went from 50+ lines of tool configuration to this:

[tool.ruff]
line-length = 120
target-version = "py312"

[tool.ruff.lint]
select = ["E", "F", "I", "N", "W"]
unfixable = ["F841"] # Don't erase variables that aren't used.

That's it.

Ruff isn't just good—it's the obvious choice. The speed alone justifies the switch, but the consolidation and reliability make it indispensable. If you're still running multiple Python linting tools, you're wasting time.

Install Ruff. Thank me later.

Back to posts
TwitterUdemyMy Twitter ProfileMy Instagram

Copyright © Kevin Katz 2025

Privacy