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

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
- 88 characters. The documentation explains that 88, "10% over 80", was found to produce significantly shorter files than 80 or 79, because fewer statements need to be split. You can change it with
--line-length; the documentation warns that lines over 100 characters are harder for people with sight disabilities and for side-by-side review. - Double quotes. PEP 8 leaves the choice open; Black prefers double quotes and converts single-quoted strings, unless that would require more backslash escapes. It also normalises string prefixes, for example removing the redundant
u. The--skip-string-normalizationoption (-S) leaves quotes alone, which helps when adopting Black on a large codebase. - Splitting. When a line is too long, Black first tries to split at the outermost brackets, putting the contents on an indented line; if that is still too long, it puts one element per line with a trailing comma.
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
- Agree on the line length and quote handling first, and write them in
pyproject.toml. - Reformat the whole codebase in one commit that contains nothing else.
- List that commit's hash in a
.git-blame-ignore-revsfile and rungit config blame.ignoreRevsFile .git-blame-ignore-revs, sogit blameskips it. Some code hosting platforms read this file automatically. - 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
- Black documentation, "The Black code style" (line length, strings, magic trailing comma) and "Stability policy".
- Black documentation, "Using Black with other tools".
- PEP 8, "When to Use Trailing Commas".
- Git documentation,
git blame --ignore-revs-file. Output above produced with Black 26.5.
Linters & formattersRuff: linter and formatter
One tool for linting, import sorting and formatting: how ruff's rule codes work, how to choose them, and what its fixes will and will not change.
PEP 8, section by sectionWhitespace and blank lines
Spaces around operators and commas, none inside brackets, two blank lines between functions: the rules, the warnings, and the one place the checker disagrees with PEP 8.
Readable code in practiceAdopting a style guide in old code
One big reformat or a gradual rollout? How to bring an old codebase in line with PEP 8 while keeping git blame useful and open branches mergeable.