Categories We Write About

Automate code formatting with Black

Automating code formatting is essential for maintaining consistent style and improving readability across a codebase. In the Python ecosystem, Black is a popular opinionated code formatter that automatically reformats Python code to conform to the PEP 8 style guide. It saves time, reduces stylistic debates, and improves the developer experience. Here’s a comprehensive guide on how to automate code formatting using Black.

What Is Black?

Black is a Python code formatter that formats code with minimal configuration. Its opinionated nature means it doesn’t allow much customization, which eliminates decision fatigue and promotes consistency. Black reformats code by parsing it into an abstract syntax tree (AST) and then generating clean, formatted code.

Key benefits include:

  • Uniform code style

  • Easy integration with development tools

  • Reduction in code review style discussions

Installation

Black can be installed using pip:

bash
pip install black

It can also be added to a project’s requirements.txt or pyproject.toml for consistent use across environments.

Basic Usage

To format a single file:

bash
black script.py

To format an entire directory recursively:

bash
black .

By default, Black will reformat the code in place. If you want to see what changes would be made without modifying the file, use the --check or --diff flags:

bash
black --check . black --diff .

Integrating with Pre-commit Hooks

One of the best ways to automate Black is by integrating it into your Git workflow using pre-commit. Pre-commit hooks ensure code is formatted correctly before any commit is made.

  1. Install pre-commit:

bash
pip install pre-commit
  1. Create a .pre-commit-config.yaml file in your project root:

yaml
repos: - repo: https://github.com/psf/black rev: 24.3.0 # use the latest version hooks: - id: black
  1. Install the hook:

bash
pre-commit install

Now, Black will automatically format code before every commit. To run the hooks on all files:

bash
pre-commit run --all-files

Integration with IDEs and Editors

VS Code

  1. Install the Python extension.

  2. Set Black as the default formatter in settings.json:

json
{ "python.formatting.provider": "black", "editor.formatOnSave": true }

PyCharm

  1. Install Black in the project environment.

  2. In Preferences > Tools > External Tools, add a new tool with:

    • Program: black

    • Arguments: $FilePathRelativeToProjectRoot$

    • Working Directory: $ProjectFileDir$

This allows formatting through a simple shortcut or context menu.

Using Black with CI/CD Pipelines

Automating formatting checks in CI/CD ensures code quality in team environments. Here’s how to add Black to a GitHub Actions workflow:

yaml
name: Black Code Formatter Check on: [push, pull_request] jobs: black-check: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - name: Set up Python uses: actions/setup-python@v4 with: python-version: '3.10' - name: Install dependencies run: | python -m pip install --upgrade pip pip install black - name: Run Black run: black --check .

This setup halts the workflow if any files are not formatted according to Black’s rules.

Configuration with pyproject.toml

While Black is mostly configuration-free, you can customize certain behaviors using pyproject.toml. This file must be placed in the root directory of the project:

toml
[tool.black] line-length = 88 target-version = ['py310'] exclude = ''' /( .git | .venv | build | dist )/ '''

You can adjust settings like line length, excluded files, and Python versions to match your project needs.

Formatting Python Code in Jupyter Notebooks

Black also supports Jupyter notebooks using the black[jupyter] extra:

bash
pip install black[jupyter]

To format notebooks:

bash
black notebook.ipynb

This ensures your notebooks remain as clean and readable as your script files.

Running Black Programmatically

You can run Black programmatically within Python scripts:

python
import black source_code = "def add(x,y):return x+y" formatted_code = black.format_str(source_code, mode=black.Mode()) print(formatted_code)

This can be useful for building developer tools, code editors, or linters that embed Black.

Best Practices

  • Enforce in CI: Prevent unformatted code from being merged into main branches.

  • Team Alignment: Ensure everyone installs and uses Black consistently, ideally through pre-commit and pyproject.toml.

  • Automate Save Hooks: Enable format-on-save in IDEs to reduce manual steps.

  • Pair with Linters: Use Black alongside linters like flake8 or ruff for full code quality enforcement.

Alternatives and Complements

While Black handles formatting, it does not catch logical errors or deeper style inconsistencies. Complementary tools include:

  • isort: Automatically sorts and organizes imports.

  • flake8 / ruff: Lint code for style and logical issues.

  • mypy: Perform static type checking.

You can integrate all of them using pre-commit for a robust automated code hygiene setup.

Conclusion

Black offers a powerful, opinionated approach to Python code formatting that enhances consistency and developer productivity. By integrating it into development environments, pre-commit hooks, and CI/CD pipelines, teams can ensure that all code adheres to a standard without requiring manual review. The simplicity and automation that Black provides make it an essential tool in any modern Python developer’s toolkit.

Share This Page:

Enter your email below to join The Palos Publishing Company Email List

We respect your email privacy

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *

Categories We Write About