← Back to tech sharing
2026-08

Making sense of Python's formatting/linting tools: isort, Black, Flake8, Pylance, Ruff

PythonLinterDevEx

Python projects tend to accumulate a pile of tools called “formatters”, “linters” and “type checkers”, and the names alone don’t tell you what each one actually does. This article covers the five most common ones — isort, Black, Flake8, Pylance and Ruff — in this order: (1) which category each tool belongs to, (2) what problem each category solves, and (3) how to actually combine them in practice.

1. Start with three categories

Python code-quality tools fall into three broad categories.

CategoryWhat it solvesRewrites your code?
FormatterNormalizes how code looks (line breaks, indentation, quote style, import order, …) according to a fixed rule setYes
Linter (static analysis)Flags patterns that tend to hide bugs (unused imports, undefined names, unsafe comparisons, …)No
Type checkerUses type hints to catch type mismatches before the code ever runsNo

Mapping the five tools onto these three categories gives:

ToolCategory
isortFormatter (import order specialist)
BlackFormatter (whole-file code style)
Flake8Linter
PylanceLeans type checker (editor language server)
RuffReimplements most of the formatter and linter categories in one tool

In other words: isort and Black are formatters, Flake8 is a linter, Pylance leans toward being a type checker, and Ruff isn’t tied to a single category — it replaces large parts of several categories at once.

2. What each tool actually does

Formatters

isort — A formatter with exactly one job: sorting import statements. It groups imports into standard-library / third-party / local-project buckets and alphabetizes each group. It’s traditionally paired with Black under a simple division of labor: “Black formats the code body, isort formats the imports.”

Black — Famous for being “opinionated”: it has almost no configuration knobs and produces one deterministic formatting result for line wrapping, quote style (double quotes by default), trailing commas, and so on. It exists specifically to end team debates (tabs vs. spaces, single vs. double quotes) by removing the choice. It only formats — it never flags bugs.

Linters

Flake8 — The classic linter for PEP8 (style guide) violations, unused imports/variables, overly complex functions, and similar issues. Flake8 itself is a thin wrapper around pyflakes (bug detection) + pycodestyle (PEP8 checks) + mccabe (complexity metrics). It never rewrites your code — there’s no auto-fix.

Type checkers

Pylance — VS Code’s Python language server, built on Microsoft’s Pyright type checker. It provides real-time autocomplete, go-to-definition, type-mismatch detection, and hover type info directly in the editor. It’s less a CI tool and more infrastructure for a good developer experience while writing code.

The cross-category consolidator

Ruff — A Rust-based static analysis and formatting tool that reimplements Flake8 itself, dozens of Flake8 plugins, isort, and (partially) pyupgrade’s rule sets in a single binary. ruff check covers linting (Flake8-equivalent), ruff format produces Black-compatible formatting, and --fix auto-corrects most findings. Its defining trait is collapsing the formatter and linter categories into one extremely fast tool (it doesn’t do type checking).

3. Comparison table

ToolTypeMain jobAuto-fixSpeedType checking
isortFormatterSorts importsYesFastNo
BlackFormatterFormats the whole fileYesNormalNo
Flake8LinterFlags PEP8/bug-prone codeNoNormalNo
PylanceLanguage server / type checkerEditor completion & type checkingPartial (Quick Fix)Fast (runs in background)Yes (Pyright)
RuffLinter + formatterFast replacement for Flake8 + isortYesVery fastNo

4. How to combine them

  • New project, want the leanest setup → Ruff alone (ruff format + ruff check --fix) covers formatting, import sorting and most lint rules. CI and editor-on-save use the exact same rules.
  • Existing project already on Black + isort + Flake8 → Don’t force a rip-and-replace; migrate gradually onto Ruff’s Flake8/isort-compatible rules, since a few rules do behave slightly differently.
  • Want stronger type safety → Neither Ruff nor Flake8 does type checking, so add Pylance (editor) and pyright/mypy (CI) separately.
  • Editor comfort is the goal → Unlike the other, CLI-only tools, Pylance runs continuously in the editor providing completion, jump-to-definition and hover info — a different purpose from CI linting. Wire Ruff or mypy into CI separately.

Summary

As of 2026, the simple, fast standard setup is: “Ruff for formatting and most linting” plus “Pylance in the editor + mypy/pyright in CI for type checking.”