#pythonIntermediate

Improve Python Code Quality with Ruff and Pre-commit

Jun 26, 2026
38 min read

AI Insights

Powered by GPT-4o-mini

Verified Context: improve-python-code-quality-with-ruff-and-pre-commit
Quick Answer

Learn Python code quality best practices with Ruff linting, Ruff formatting, import sorting, pyproject.toml configuration, type hints, pre-commit hooks, and CI checks.

Quick Summary

Learn how to use Ruff for linting, formatting, and type hints in Python. Enhance your code quality with pre-commit hooks and CI integration.

Python Code Quality with Ruff, Formatting, Import Sorting, Type Hints, and pre-commit

Quick Answer

Use Ruff to lint and format Python code.

bash
ruff check .
ruff format .

Keep Ruff configuration in pyproject.toml, and add pre-commit hooks when the project becomes important.

Last verified: June 26, 2026.

What You Will Learn

By the end, you should be able to:

  • explain linting vs formatting
  • install and run Ruff
  • configure Ruff in pyproject.toml
  • sort imports
  • format code consistently
  • add useful type hints
  • set up pre-commit hooks
  • run code quality checks in CI

1. What Is Code Quality?

Code quality means the project is easy to read, change, and review.

Good code quality includes:

  • consistent formatting
  • clean imports
  • no unused variables
  • clear names
  • simple functions
  • useful type hints
  • predictable tooling

Tools do not replace judgment, but they remove repetitive review work.

2. Linting vs Formatting

Linting finds problems.

Examples:

  • unused imports
  • undefined names
  • bad exception patterns
  • overly complex code

Formatting rewrites code style.

Examples:

  • line wrapping
  • spacing
  • quote normalization
  • indentation

Ruff can do both.

3. Install Ruff

bash
python -m pip install ruff

If you use pyproject.toml:

toml
[project.optional-dependencies]
dev = [
  "ruff>=0.5",
]

Run:

bash
ruff --version

4. Run Ruff Checks

bash
ruff check .

Automatically fix safe issues:

bash
ruff check . --fix

Be careful with automatic fixes on large uncommitted changes. Review the diff.

5. Format With Ruff

bash
ruff format .

Check formatting without changing files:

bash
ruff format --check .

Use this in CI.

6. Configure Ruff In pyproject.toml

Basic configuration:

toml
[tool.ruff]
line-length = 88
target-version = "py312"

[tool.ruff.lint]
select = ["E", "F", "I", "B", "UP"]
ignore = []

Useful rule families:

CodeMeaning
Epycodestyle errors
FPyflakes
Iimport sorting
Bbugbear-style warnings
UPmodern Python upgrades

Start small. Add stricter rules when the team is ready.

7. Import Sorting

Messy imports:

python
from pathlib import Path
import pandas as pd
import os
from my_app.config import Settings

Ruff can sort them:

python
import os
from pathlib import Path

import pandas as pd

from my_app.config import Settings

Run:

bash
ruff check . --select I --fix

8. Keep Functions Small

Long functions are hard to test.

Instead of one function that reads a file, cleans data, calls an API, writes output, and prints a report, split responsibilities:

python
def read_orders(path):
    ...

def clean_orders(df):
    ...

def summarize_orders(df):
    ...

def write_report(summary, path):
    ...

Small functions make tests and reviews easier.

9. Use Clear Names

Weak:

python
def f(x):
    return x * 1.18

Better:

python
def price_with_gst(base_price: float) -> float:
    return base_price * 1.18

Names should describe intent, not just data type.

10. Add Type Hints Where Useful

python
def normalize_slug(title: str) -> str:
    return title.strip().lower().replace(" ", "-")

Type hints are most useful on:

  • public functions
  • service functions
  • parsing functions
  • config objects
  • functions used by many files

Do not let typing slow beginner learning too much. Add it where it clarifies.

11. Avoid Bare Except

Weak:

python
try:
    value = int(raw)
except:
    value = 0

Better:

python
try:
    value = int(raw)
except ValueError:
    value = 0

Catch the specific exception you expect.

12. Avoid Mutable Defaults

Weak:

python
def add_item(item, items=[]):
    items.append(item)
    return items

Better:

python
def add_item(item, items=None):
    if items is None:
        items = []
    items.append(item)
    return items

Linters help catch this.

13. Add pre-commit

Install:

bash
python -m pip install pre-commit

Create .pre-commit-config.yaml:

yaml
repos:
  - repo: https://github.com/astral-sh/ruff-pre-commit
    rev: v0.5.0
    hooks:
      - id: ruff
        args: [--fix]
      - id: ruff-format

Install hooks:

bash
pre-commit install

Run on all files:

bash
pre-commit run --all-files

14. Add Code Quality To CI

GitHub Actions example:

yaml
name: Python quality

on: [push, pull_request]

jobs:
  quality:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v5
        with:
          python-version: "3.12"
      - run: python -m pip install -e ".[dev]"
      - run: ruff check .
      - run: ruff format --check .
      - run: pytest

CI ensures checks run even if someone skips local hooks.

15. Code Quality Checklist

Before sharing a project, confirm:

  • Ruff runs cleanly
  • formatting is consistent
  • imports are sorted
  • functions are not doing too much
  • names explain intent
  • specific exceptions are caught
  • public functions have useful type hints
  • pre-commit is configured for important projects
  • CI runs lint, format check, and tests

16. FAQ

Is Ruff a replacement for Black and isort?

Ruff can format code and sort imports, so many projects use Ruff instead of separate Black and isort tools.

Should beginners use Ruff?

Yes, but start with a small configuration. Do not enable every strict rule on day one.

Should I run ruff --fix automatically?

For small changes, yes. For large existing projects, run it carefully and review the diff.

Do type hints make Python faster?

Usually no. Type hints mainly help humans and tools understand your code.

Is pre-commit required?

No, but it is useful when a project has multiple contributors or repeated quality checks.

Frequently Asked Questions

What is the difference between linting and formatting?
Linting finds problems such as unused imports and overly complex code, while formatting rewrites code style, including line wrapping and indentation. Ruff can perform both tasks.
How can you install Ruff?
You can install Ruff using pip with the command 'python -m pip install ruff'. If using pyproject.toml, include Ruff in the optional dependencies.
How do you configure Ruff using pyproject.toml?
Basic configuration in pyproject.toml includes setting line-length, target-version, and selecting rule families like 'E', 'F', 'I', 'B', and 'UP'.
What are some examples of code quality features?
Good code quality includes consistent formatting, clean imports, no unused variables, clear names, simple functions, and useful type hints.
Why should functions be kept small?
Small functions are easier to test and review, as they have focused responsibilities and can be individually verified.

Related Work

See how this thinking shows up in shipped systems.