Formatting and Linting Python Code with isort, black, and flake8
When working on Python projects, maintaining clean and consistent code is critical for readability, maintainability, and collaboration. Tools like isort, black, and flake8 simplify this process by automating code formatting and linting.
In this blog post, we’ll explore these tools, their features, and how to integrate them with a pre-commit hook for seamless code management. We’ll also dive into the role of pyproject.toml
in consolidating configuration settings.
Why Use isort, black, and flake8?
1. isort
isort automatically sorts and organizes Python imports. Clean import statements make your code easier to read and prevent common issues, like circular imports or unused imports.
Key Features:
- Groups imports into sections (standard library, third-party, and local imports).
- Automatically removes unused imports.
- Configurable via
pyproject.toml
or other configuration files.
Example:
Before:
import os
from django.conf import settings
import sys
After (using isort
):
import os
import sys
from django.conf import settings
2. black
black is an uncompromising code formatter for Python. Its goal is to standardize formatting, eliminating debates over style choices.
Key Features:
- Opinionated and consistent: Adheres to PEP 8 by default.
- Supports most Python versions.
- Automatically reformats code for readability.
Example:
Before:
def greet(name): print(f"Hello, {name}")
After (using black
):
def greet(name):
print(f"Hello, {name}")
3. flake8
flake8 is a linter that checks your code against PEP 8 standards and identifies errors and potential bugs.
Key Features:
- Detects syntax errors and undefined variables.
- Integrates with plugins for extended functionality (e.g., cyclomatic complexity checks).
- Outputs detailed reports to help fix issues.
Example:
Code with issues:
def add(a,b):return a+b
Issues flagged by flake8
:
- Missing spaces around the
+
operator. - Function definition not compliant with PEP 8.
Fixed code:
def add(a, b):
return a + b
Using isort, black, and flake8 Together
These tools complement each other. Here’s how they interact:
- isort handles import organization.
- black formats the entire code, including line breaks and indentation.
- flake8 ensures code adheres to PEP 8 and identifies bugs.
Running isort, black, and flake8 Explicitly
You can run these tools directly from the command line to check or format your code:
Run isort
Sort imports with:
isort .
Check for unsorted imports without changing files:
isort . --check-only
Run black
Format your code:
black .
Check formatting without making changes:
black . --check
Run flake8
Check code for linting issues:
flake8 .
Setting Up Pre-Commit Hook
Pre-commit is a framework for managing and running pre-commit hooks. By integrating isort
, black
, and flake8
into your workflow, you ensure that code is formatted and linted before being committed.
Steps to Set Up:
- Install Dependencies:
pip install isort black flake8 pre-commit
2. Create a .pre-commit-config.yaml
File: This file defines the hooks to run before each commit.
repos:
- repo: https://github.com/pycqa/isort
rev: 5.12.0
hooks:
- id: isort
name: isort
args: ["--profile", "black"]
- repo: https://github.com/psf/black
rev: 23.1.0
hooks:
- id: black
name: black
- repo: https://github.com/PyCQA/flake8
rev: 7.0.0
hooks:
- id: flake8
args: ["--exclude=venv,.venv,__pycache__,.git"]
3. Install Pre-Commit Hooks: Run the following command to install hooks:
pre-commit install
4. Test the Setup: Run all hooks manually:
pre-commit run --all-files
Now, every time you commit code, isort
, black
, and flake8
will automatically process your files.
The Role of pyproject.toml
The pyproject.toml
file serves as a centralized configuration file for Python tools. It simplifies project setup by consolidating settings for tools like isort
, black
, and others.
Example Configuration:
[tool.black]
line-length = 79
target-version = ["py311"]
include = '\.pyi?$'
exclude = '''
/(
\.git
| \.hg
| \.mypy_cache
| \.tox
| \.venv
| _build
| buck-out
| build
| dist
| venv
| \.env
| \.flake8
)/
'''
[tool.isort]
profile = "black"
line_length = 79
known_third_party = ["django"] # Add other third-party libraries as needed
src_paths = ["src", "apps"] # Adjust paths as per your project structure
[tool.flake8]
max-line-length = 79
extend-ignore = ["E203", "W503"] # For compatibility with Black (optional)
Why Use pyproject.toml
?
- Reduces clutter by replacing multiple configuration files.
- Enhances portability and consistency.
- Supported by most modern Python tools.
Putting It All Together
Here’s how the workflow looks with isort
, black
, flake8
, and pre-commit
:
- Write your Python code.
- Run
pre-commit
hooks when committing changes. - Let
isort
organize imports,black
format the code, andflake8
check for issues. - Fix any errors flagged by
flake8
and repeat as needed.
Conclusion
Using isort
, black
, and flake8
together ensures clean, readable, and error-free Python code. Integrating these tools with pre-commit
hooks and configuring them via pyproject.toml
streamlines the development process. Whether you’re a beginner or an experienced developer, these tools are essential for maintaining high-quality code.