Skip to content(if available)orjump to list(if available)

Ruff: Python linter and code formatter written in Rust

scosman

Being new to python, the astral stuff is such a relief.

I don’t think experienced python folks realize how much the flexible tooling slows people down, and creates friction for adopters. Setting up my project I tried 3 environment managers, 2 type checkers, 3 formatters/linters, 3 packagers/dependancy/project managers.

I know this is kinda the n+1 issue where astral is just adding another. But it feels like a complete and well designed stack, not a box of parts encouraging me to build my own. Reminds me a bit of go tooling.

I am a convert. I’ll happily jump on their type checker and packager when ready.

kstrauser

I’ve been writing Python for 25 years and I love love love ruff and uv and friends.

rikthevik

I'm very impressed by the recent developer experience improvements in the python ecosystem. Between ruff, uv, and https://github.com/gauge-sh/tach we'll be able to keep our django monolith going for a long time.

Any opinions about the current state of the art type checker?

Mehdi2277

I'm very happy with pyright. Most bug reports are fixed within a week and new peps/features are added very rapidly usually before pep is accepted (under experimental flag). Enough that I ended up dropping pylint and consider pyright enough for lint purposes as well. The most valuable lints for my work require good multi-file/semantic analysis and pylint had various false positives.

Main tradeoff is this only works if your codebase/core dependencies are typed. For a while that was not true and we used pylint + pyright. Eventually most of our code is typed and we added type stubs for our main untyped dependencies.

edit: Also on pylint, it did work well mostly. tensorflow was main library that created most false positives. Other thing I found awkward was occasionally pylint produces non-deterministic lints on my codebase.

__tyler__

I have always used MyPy but I have noticed some large open source projects adopt Pyright as of late. The folks behind ruff and uv are currently working on a type checker as well but haven't heard when they plan on releasing it.

danpalmer

I'm a little sad that Ruff took off as a re-implementation of a whole bunch of work that was already done, rather than as a project to improve the work that was already done.

It was nice to be able to write little extra linters or flake8 plugins in the language I was linting. Plus decades of effort had gone into making those plugins pretty great, finding the right separation of linting codes so that the right things could be linted/ignored per codebase.

I understand why they did it, and they have done it remarkably well, but "rewrite it from scratch" is almost never the best answer and part of me wonders if this result could have been even better achieved another way.

thrdbndndn

I'm also sad but from a different perspective.

If something can be rewritten from scratch fairly quickly and ends up being much faster, it makes you wonder what we (the general “we”) might have done “wrong” with the “decades of effort” before.

To be clear: there was nothing wrong with the old toolchains (hence the quotes). And of course, Ruff/uv can do what they do because they build on all that earlier knowledge. My point is just that sometimes it's easier to start over than to fix the old, and that fact itself feels kind of sad to me.

zahlman

> My point is just that sometimes it's easier to start over than to fix the old, and that fact itself feels kind of sad to me.

Sad, but also liberating. There are surely more projects out there that would benefit from breaking with conventional wisdom to start over.

n8henrie

I am quite grateful that they rewrote so many tools that I had been using. Upgrades were super painful with them split into a dozen separate packages, I routinely ran into incompatibilities and had to pin to specific versions to deal with transitive dependencies.

Given the state of python packaging and tooling, I'd say that consolidating the tooling is a big win in and of itself, and with the tremendous speed wins on top...

FreakLegion

Whenever Ruff comes up, I reflexively go and check https://github.com/astral-sh/ruff/issues/970, since Pylint is the one tool whose performance I find to be egregiously bad. Looks like Ruff is still very far from being able to replace it.

eviks

> this result could have been even better achieved another way.

Don't you have "decades of effort" to resolve this wonder?

searealist

Your argument seems ideological. There is no chance they could have improved Flake8 to be as good as Ruff is.

burntsushi

Folks said the same thing to me about grep 8.5 years ago when I released ripgrep.

JelteF

Wait... Did you misunderstand this comment? Or are you saying grep caught up with ripgrep now?

oguz-ismail

And you think you've done it?

danpalmer

Yeah it's somewhat ideological, I think open source software is better for society when built as a community project than built and controlled by a VC funded company.

I don't think you could get flake8 to be as fast as Ruff, but I think you could improve it to be within an order of magnitude, and honestly that's plenty good enough. There are a lot of low hanging fruit, particularly around caching. I'd push back on there being no chance of being "as good as" Ruff, because "good" is not just speed. Ruff is _not complete_, if you want all the features and linters, you still need Flake8, or you have to sacrifice some. It's also not publicly extensible, and not written in Python, both of which are fair choices but I think deviate from the ideal scenario here.

Onavo

Blame Guido. Until recently when he was bought out by Microsoft, he had been the primary blocker of higher Python performance. There were a bunch of attempts at adding a JIT to Python but Guido was more interested in splitting hairs over syntax than any real heavy lifting. Python could have been as performant as LuaJIT or V8 but their dictator ruined it. Python need more Mike Palls.

throwaway98231

At this point I think even people trapped for two years on the International Space Station have heard about the Astral toolchain.

thrdbndndn

Any more info about "Astral" the org?

I've used ruff/uv for sure, but I never pay attention to Astral who is behind it.

ericjmorey

VC funded organization. Not sure what their business model is yet.

hartator

Astral toolchain?

zahlman

Python development tools produced by Astral (https://github.com/astral-sh), primarily uv and ruff. GP is a complaint about how often people submit links to these projects. The resulting discussion tends not to produce any new insight and the most common points IMX are "it's fast because it's written in Rust" (which is fairly specious logic - most problems with existing native Python tools are due to algorithmic problems such as poorly designed caching) or "it avoids bootstrapping problems because it's not written in Python" (it's completely possible to avoid those problems for everything except actually provisioning the Python interpreter, which some people apparently do see as a killer feature).

mrits

Maybe, I use uv and rust has been my primary language for several years. I have never heard of astral though.

zahlman

Astral is the organization making uv. It's right there in the GitHub URL.

mrits

How do you read me comment and take away that I still dont know what Astral is? You acted like everyone had heard of it. My point is not even all the users of uv have.

tiltowait

It really is as fast as it claims. I sometimes intentionally add something it will complain about just to make sure it’s still working.

atty

I do the same thing, and I keep doing it regardless of how many times I see it working properly.

mhh__

A small boon to it not being in python — it's now decoupled from your python toolchain.

zahlman

There is no "coupling" inherent to native Python tools. They can generally be installed in a separate virtual environment from the one they operate on.

For example, with Pip you simply pass the `--python` option to have it install for a different environment - you can create your venvs `--without-pip`, and share a copy of Pip across all of them. If you use Pipx, you can expose and use Pipx's vendored Pip for this, as I described in a recent blog post (https://zahlman.github.io/posts/2025/01/07/python-packaging-...).

Twine and Build don't care about your project's environment at all - Twine uploads a specified file, and Build by default creates a new environment for the build (and even withough build isolation, it only requires your build environment to contain the build backend, and the build environment doesn't have to be the one you use for the rest of development). Setuptools, similarly, either gets installed by the build frontend into an isolated build environment, or can reside in a separate dedicated build environment. It doesn't actually operate on your project's environment - it only operates on your project's source tree.

monomial

I've been using an amalgamation of pyenv, pip-tools, black, isort, etc. for projects and just gave uv and ruff a try. Wow, it really is fast! Skeptical of anything VC-backed but I'll be keeping my eye on it.

Blackarea

I don't care one bit about py-land, but it's always nice to see a rust project swoope in and save the day.

Language processing like compiling or linting is just one of the many aspect where rust can really play out it's awesome strength.

seanwilson

For Django projects, what's fast that will cover Python, HTML, CSS and JavaScript files? Ruff only does Python?

bobbylarrybobby

Prettier can do HTML CSS and JS but I don't think there's any one tool that can do it all. (It would be interesting if there were something like a tree sitter for auto formatting)

null

[deleted]

greatgib

So much marketing coolaid/bullshit.

I'm not that fan of Ruff because to me it doesn't make any sense to add a rust dependency to "python" and it blows my mind that people are so keen to accept the ugly formatting inherited from Black just because "it gives consistency to the team, so I don't have to think, and we don't have to discuss code style"...

But all of that personal opinion set aside, what triggers my initial statement is that so many persons are so excited to run to use Ruff because... "It is so fast"... when I'm quite sure most of them would never notice any real speed difference with their modest codebase.

In almost all the codebases I have seen, proprietary and OSS, pylint or any other linter was quasi-instant. There are probably a few huge codebases that would see a speed benefit of a few seconds to use Ruff, but their owner would probably better have a look at their code to understand how their reached such a monster!

Terretta

> quite sure most of them would never notice any real speed difference with their modest codebase

On the contrary, within only a year or so of coding by a small team, this ecosystem takes single digit seconds or less, while the traditional tools are taking minutes and more.

Particularly in analytics or scientific computing we've seen minutes versus under a second.

Having the tools not require additional/parallel Python dependency management is a plus.

Note that we watched these tools for a long time, and jumped in when rye converged with uv. It was promising to see fewer ways to do it.

// More on that here: https://news.ycombinator.com/item?id=41309072

ak217

I don't know what kinds of codebases you've worked with, but I can tell you that pylint is so far from instant, it became the longest running CI job in multiple reasonably sized codebases I've worked with. Think tens of minutes. Other linters were not much better, until ruff came along. But that's far from the only advantage that ruff brings.

There are other issues with what you said, but the biggest one is: you have some strongly worded criticism for a project that has set a new bar for usability and consistency in Python code quality tooling. These tools are developed by humans like you and distributed to you for free with no obligation to use them. No matter how I look at your comment, I don't see how it's helping.

zahlman

I'm confused: why are you linting code in CI, rather than as a precommit hook?

sunshowers

Well, for one, I use Jujutsu, where commits happen every time you run jj status and traditional notions of pre-commit hooks don't really apply. But also, I think (as a matter of principle) nothing should get in the way of performing commits or amends.

ak217

Pre-commit hooks are great in small, focused codebases with small, homogeneous teams. In large monorepos with lots of different teams committing, it's impossible to guarantee any kind of consistency in which pre-commit hooks get run, so you need CI to actually enforce the consistency or you'll spend all your time chasing (accidental) violations.

kstrauser

Because devs can disable precommit hooks much more easily than they can work around CO.

I see precommit hooks as where you avoid the low-hanging fruit, like “is this code actually parsable?”

rmwaite

I have issues with some of Black’s formatting decisions but I’ve also suffered from inconsistent formatting and there is no question in my mind that consistent formatting that I find ugly sometimes is 1000% better than the alternative. And after so many years of dealing with it it’s so refreshing to just “give up” and let the formatter win.

kstrauser

Same here. I appreciate that Black annoyed everyone on our team about the same amount but in different ways. From the instant we added it, stupid style arguments completely disappeared.

Know what I care about more than Black making my own code look less pretty? It making my coworker’s code look less horrid. (And funnily, I’m certain everyone on the team thinks exactly that same thing.)

sunshowers

Personally, I think excellence is a virtue in tooling in and of itself. The Python world just hasn't experienced this kind of excellence before.

thayne

I like that it's fast, and it is noticeably faster for even moderately sized codebases.

But the main thing I like about ruff is that it is a single tool with consistent configuration, as opposed to a combination of several different tools for formatting and linting that each have their own special way of configuring them and marking exceptions to lint rules.

paulgb

Doesn’t Black mostly stick to PEP-8 style? What rules do you consider ugly?