Linters & formatters

Black, the Python Code Formatter: How It Works and How to Configure It

Linters & formatters · · Published 2026-10-27

An engraving of a two-handled printer's composition roller used for inking type
A composition hand roller for inking type, from a 1906 American Type Founders catalogue. Public domain.

Black calls itself "the uncompromising Python code formatter". Instead of reporting style problems, it rewrites files into one consistent layout, and it deliberately offers very few options. The idea is that once formatting is automatic, nobody needs to discuss it again, in review or anywhere else.

What Black does

Black parses your code and prints it again in its own style, ignoring the previous layout. According to its documentation, its rules for horizontal whitespace can be summarised as "do whatever makes pycodestyle happy", and for vertical layout it tries to put one full expression or simple statement per line. It also checks that the reformatted code produces the same syntax tree as the original, so formatting cannot change what a program does.

Here is a short, untidy file and the diff Black produced:

def make_order(customer, items, discount=None, express=False, gift_wrap=False, note=''):
    return {'customer': customer, 'items': items, 'discount': discount}
colors = ['red', 'green',]
point = {'x':1,'y':2}
result = make_order("ana", [1,2,3], note = 'leave at door')
def make_order(customer, items, discount=None, express=False, gift_wrap=False, note=""):
    return {"customer": customer, "items": items, "discount": discount}


colors = [
    "red",
    "green",
]
point = {"x": 1, "y": 2}
result = make_order("ana", [1, 2, 3], note="leave at door")

Quotes became double quotes, spaces were fixed after colons and commas and removed around the keyword argument, and two blank lines were added after the function. The def line stayed whole: it fits within Black's 88-character default, although pycodestyle at its default of 79 would report it as E501.

The defaults, and the reasons for them

The magic trailing comma

The colors list in the example fit on one line, yet Black exploded it. The reason is the comma after 'green'. Black treats a pre-existing trailing comma as a signal that you want the collection one item per line, and keeps it that way. Remove the comma, and Black joins the list again if it fits. This gives you one deliberate lever over layout, and it follows PEP 8's advice on trailing commas for lists that are expected to grow. The --skip-magic-trailing-comma option turns the behaviour off.

Configuration

Black reads its settings from the [tool.black] table of pyproject.toml:

[tool.black]
line-length = 88
target-version = ["py312"]
extend-exclude = "migrations/"

target-version tells Black which Python versions the code must run on, which affects syntax choices such as parenthesised context managers. For code that must keep a hand-made layout, such as a carefully aligned matrix, # fmt: off and # fmt: on around a block, or # fmt: skip at the end of a line, exclude it from formatting. Use them rarely: each one is a small exception to "nobody needs to think about formatting".

Stability

A formatter that changes its output often would create noisy diffs. Black's stability policy addresses this: code formatted with Black "will remain unchanged when formatted with the same options using any other release in the same calendar year". The first release of a new year may include style changes, previewed during the previous year under the --preview flag. In practice, projects pin Black's version, for example with a compatible-release specifier such as black ~= 26.0, and upgrade deliberately, reformatting in a single commit.

Working with linters and isort

Black follows PEP 8, but some linter checks are stricter than PEP 8 or contradict it. Black's documentation recommends this minimal flake8 configuration:

[flake8]
max-line-length = 88
extend-ignore = E203,E701

E203 is disabled because Black puts spaces around the colon in complex slices, as PEP 8 allows. E701 and E704 concern one-line bodies such as class Empty: ..., which Black can produce for stub-like definitions. W503 should stay disabled, as it is by default, because Black breaks lines before binary operators. For pylint, set max-line-length = 88. For import sorting with isort, use its black profile. Our article on whitespace and blank lines explains the slice rule in detail.

Adopting Black on an existing project

  1. Agree on the line length and quote handling first, and write them in pyproject.toml.
  2. Reformat the whole codebase in one commit that contains nothing else.
  3. List that commit's hash in a .git-blame-ignore-revs file and run git config blame.ignoreRevsFile .git-blame-ignore-revs, so git blame skips it. Some code hosting platforms read this file automatically.
  4. Add black --check . to CI and, ideally, a pre-commit hook.

Our guide to adopting a style guide in an existing codebase covers the wider process.

Black, or ruff format?

ruff includes a formatter designed as a drop-in replacement for Black, producing nearly identical output, with its documentation listing the known differences. Projects that already use ruff for linting often use its formatter too, to have one tool instead of two. Both read their settings from pyproject.toml; see our guide to ruff. For a quick check that does not change anything, the checker on our home page reports the whitespace issues a formatter would fix.

Sources