What Does Black Do? Python’s Code Formatter Explained

How Black formats Python code, why it’s deliberately unconfigurable, and how it differs from autopep8 and yapf

Black reformats your Python source code to a single, consistent style — automatically, on every save or commit, with almost no configuration options. That last part is the point, not a limitation.

What it actually changes

Run black . on a project and it rewrites: quote style (double quotes, with narrow exceptions), line length (88 characters by default), trailing commas, whitespace around operators, indentation consistency, and how it wraps long function calls, lists, and dicts across multiple lines. It doesn’t touch logic — only formatting.

# before
def greet(name,greeting='Hello'):
    return(greeting+", "+name+"!")

# after black
def greet(name, greeting="Hello"):
    return greeting + ", " + name + "!"

Why “uncompromising” is the actual feature

Older formatters like autopep8 and yapf are configurable — you choose quote style, line length, bracket wrapping rules, and so on. That sounds like a feature until a team spends real meeting time arguing over tabs vs spaces or single vs double quotes. Black deliberately offers almost none of that. You run it, it produces one specific output, and the debate ends. The trade-off is you don’t get to have opinions about the formatting — but most teams that adopt Black report that’s exactly the relief they wanted.

Black vs autopep8 vs yapf

  • autopep8 fixes PEP 8 violations but leaves most stylistic choices (quote style, wrapping) up to you — it’s a linter-compliance tool, not a full reformatter.
  • yapf (Google’s formatter) is highly configurable, closer to clang-format’s philosophy of “configure it to match your house style.”
  • Black picks one style and applies it uniformly, with configuration limited mostly to line length and a small set of target Python versions.

If your team wants a formatter with zero bikeshedding potential, Black is the default choice today — it’s what Ruff’s formatter also targets compatibility with, if you’re already using Ruff for linting and want one less tool. For a fuller breakdown including Ruff’s format-plus-lint combination, see Black vs Ruff vs autopep8 vs yapf.

Configuring Black

There genuinely isn’t much to configure, and that’s intentional — but the handful of options that exist live in pyproject.toml under [tool.black]:

[tool.black]
line-length = 100
target-version = ["py312"]
skip-string-normalization = true

line-length overrides the 88-character default. target-version tells Black which Python syntax features it’s safe to assume when formatting. skip-string-normalization is the one escape hatch if you don’t want Black converting single quotes to double quotes — everything else about Black’s style is fixed and isn’t meant to be tuned.

Running it in practice

Most projects run Black as a pre-commit hook or a CI check (black --check . fails the build on unformatted code) rather than trusting developers to remember to run it manually. Editor integrations (format-on-save) are common enough that in a Black-adopting codebase, you often never think about formatting at all.

Frequently Asked Questions

What does Black actually do to Python code?

Black automatically reformats Python source code to a single, consistent style — quote style, line length, whitespace, trailing commas, and how it wraps long function calls, lists, and dicts. It doesn’t change logic, only formatting.

Why is Black described as “uncompromising”?

Unlike autopep8 or yapf, Black offers almost no configuration options. It produces one specific output for a given input, removing formatting debates (tabs vs spaces, quote style) from a team’s discussions entirely.

How does Black differ from autopep8 and yapf?

autopep8 fixes PEP 8 violations but leaves most stylistic choices up to you. yapf is highly configurable, similar to clang-format. Black picks one style and applies it uniformly, with configuration limited mostly to line length.

Can you configure Black at all?

Yes, but minimally — line-length, target-version, and skip-string-normalization in pyproject.toml under [tool.black]. Everything else about Black’s style is fixed by design.

How do most teams run Black?

As a pre-commit hook or a CI check (black —check .) rather than relying on developers to run it manually, often paired with an editor’s format-on-save integration.