This guide shows you how to automatically format your Python code using Black and isort, so your project stays clean, consistent, and easy to read (even at 3 a.m. after too much coffee).
What Are Black and isort?
- Black: An opinionated Python code formatter that auto-formats your code to follow PEP 8 style (so you can stop arguing about whitespace with your teammates).
- isort: Automatically sorts and organizes your imports into neat, logical sections.
⚠️ Heads up: Black and isort can sometimes fight over formatting. To avoid this, always configure isort to use Black’s style.
Installing Black and isort
# Install both tools
pip install black isort
# Or add them as dev dependencies with uv
uv add black isort --dev
How to Use Black and isort
Using Black
# Format a single file
black your_file.py
# Format an entire directory
black your_directory/
# Format specific files
black file1.py file2.py
# Check what would be changed (without modifying)
black --check your_file.py
# Format all Python files in the current directory
black .
Using isort
# Sort imports in a single file
isort your_file.py
# Sort imports in an entire directory
isort your_directory/
# Sort imports in specific files
isort file1.py file2.py
# Check for changes without actually changing files
isort --check-only your_file.py
Configuring Black and isort
Black
Create a pyproject.toml in your project root (if you’re using uv, it may already exist):
[tool.black]
line-length = 88
target-version = ['py38']
include = '\.pyi?$'
exclude = '''
/(
\.git
| \.hg
| \.mypy_cache
| \.tox
| \.venv
| _build
| buck-out
| build
| dist
)/
'''
isort
Add this to the same pyproject.toml:
[tool.isort]
profile = "black"
multi_line_output = 3
line_length = 88
Setting
profile = "black"makes sure isort and Black play nicely together.
IDE Integration
VS Code
{
"[python]": {
"editor.formatOnSave": true,
"editor.codeActionsOnSave": {
"source.organizeImports": true
},
"editor.defaultFormatter": "black"
}
}
PyCharm
- Install the BlackConnect plugin.
- Install the isort plugin.
- Configure both under Settings → Tools.
Before and After Example
Before
from datetime import datetime
import os
import sys
from typing import List,Dict
def my_function( x: int,y: int )->int:
return x+y
After Black and isort
import os
import sys
from datetime import datetime
from typing import Dict, List
def my_function(x: int, y: int) -> int:
return x + y
Best Practices
- Use the same config across your team: Avoid “it works on my machine” chaos.
- Set up pre-commit hooks: Auto-format code before you even push.
- Add checks to CI/CD: Stop bad formatting from sneaking in.
- Document your rules: Put them in the README so everyone stays on the same page.
Troubleshooting
Common Issues
-
Black and isort fighting?
- Use
profile = "black"in isort. - Run isort first, then Black.
- Use
-
Line length conflicts?
- Set the same
line-lengthin both tools.
- Set the same
-
Imports not sorting right?
- Use
--profile blackwith isort. - Double-check your config sections.
- Use
Advanced Usage with Ruff
Ruff is a lightning-fast linter and formatter (written in Rust) that can replace Black, isort, and other tools — all in one go.
Why Use Ruff?
- Super fast: Like, really fast.
- All-in-one: Formatting and linting together.
- Compatible with Black style: No fighting.
- Tons of rules: Supports over 800 lint rules.
- Modern and reliable: Built for speed and correctness.
Installing Ruff
# Install with pip
pip install ruff
# Or with uv
uv add ruff --dev
Using Ruff
# Lint code
ruff check .
# Format code
ruff format .
# Auto-fix issues
ruff check --fix .
# Fix and format in one go
ruff check --fix . && ruff format .
Ruff Configuration
Add to pyproject.toml:
[tool.ruff]
line-length = 88
select = ["ALL"]
ignore = ["E501", "D203", "D212"]
target-version = "py38"
[tool.ruff.format]
quote-style = "double"
indent-style = "space"
skip-magic-trailing-comma = false
line-ending = "auto"
VS Code Integration
- Install the Ruff extension.
- Add to your
settings.json:
{
"[python]": {
"editor.formatOnSave": true,
"editor.codeActionsOnSave": {
"source.fixAll": "explicit",
"source.organizeImports": "explicit"
},
"editor.defaultFormatter": "charliermarsh.ruff"
}
}
Before and After with Ruff
- Before
from datetime import datetime
import os
import sys
from typing import List,Dict
def my_function( x: int,y: int )->int:
return x+y
- After
import os
import sys
from datetime import datetime
from typing import Dict, List
def my_function(x: int, y: int) -> int:
return x + y
Conclusion
Whether you stick with Black and isort or switch to Ruff for an all-in-one approach, keeping your code consistently formatted will make your life (and your teammates’ lives) so much easier. No more nitpicking over spaces or import orders — just clean, readable code every time.
Now go make your code beautiful and keep those diffs clean!