Ruff: Сверхбыстрый линтер и форматтер для Python с примерами
Ruff: Сверхбыстрый линтер и форматтер для Python с примерами
Введение
В мире Python-разработки поддержка чистоты кода критически важна. Традиционно для этого используются:
- Линтеры (flake8, pylint) — анализ ошибок и стиля
- Форматтеры (black, autopep8) — автоматическое форматирование
- Инструменты сортировки импортов (isort)
Проблема: Множество инструментов = сложная настройка + медленная работа.
Решение: Ruff — инструмент на Rust, объединяющий функциональность линтера, форматтера и сортировщика импортов с фокусом на скорости и удобстве.
Ключевые особенности
- Невероятная скорость (в 10-100 раз быстрее аналогов)
- 700+ встроенных правил (совместимость с flake8, isort, pyupgrade)
- Автофикс для 50%+ правил
- Форматирование кода (альтернатива black)
- Простая установка — один бинарный файл
- Современный стандарт — поддержка Python 3.12, Jupyter Notebooks
Установка
pip install ruff
# Или для изолированного окружения:
pipx install ruff
Проверка установки:
ruff --version
# ruff 0.3.4
Базовое использование
Линтинг всех файлов в проекте
ruff check .
Пример вывода:
main.py:5:17: E225 [*] Missing whitespace around operator
utils.py:1:8: F401 [*] `os` imported but unused
...
Found 12 errors.
[*] 8 fixable with the `--fix` option.
Автоматическое исправление ошибок
ruff check --fix .
Форматирование кода
ruff format .
Примеры правил с объяснением
1. Логические ошибки (F-правила)
F601: Повторяющийся ключ в словаре
# До
config = {"port": 8080, "host": "localhost", "port": 8000}
# После автофикса
config = {"host": "localhost", "port": 8000}
F841: Неиспользуемая переменная
# До
def calculate():
result = 42 # Переменная не используется
return 100
# После автофикса
def calculate():
return 100
2. Стиль кода (E, W-правила)
E711: Сравнение с None через is
# До
if value == None:
pass
# После
if value is None:
pass
W292: Отсутствие пустой строки в конце файла
# До
print("Hello")
# Файл заканчивается без \n
# После
print("Hello")
# Добавляется \n в конце
3. Сортировка импортов (I-правила)
I001: Несортированные импорты
# До
import sys
import os
from django.conf import settings
# После
import os
import sys
from django.conf import settings
4. Форматирование (RUF-правила)
RUF100: Ненужные noqa
# До
import os # noqa: F401
# После (комментарий удаляется)
import os
Конфигурация через pyproject.toml
Пример настройки:
[tool.ruff]
line-length = 100
select = [
"E", # pycodestyle errors
"F", # Pyflakes
"I", # isort
"UP", # pyupgrade
"RUF", # ruff-specific
]
ignore = ["E501"] # Игнорировать длинные строки
# Настройка форматирования
[tool.ruff.format]
quote-style = "single" # Использовать одинарные кавычки
indent-width = 4
# Настройка isort
[tool.ruff.isort]
known-first-party = ["myapp"]
Интеграция в IDE (VS Code)
- Установите расширение
Ruff - Добавьте в
settings.json:
{
"python.linting.enabled": true,
"python.linting.ruffEnabled": true,
"editor.codeActionsOnSave": {
"source.fixAll.ruff": true
},
"python.formatting.provider": "ruff"
}
Результат: автоматический линтинг и форматирование при сохранении файла.
Работа с Jupyter Notebooks
ruff check --format jupyter notebook.ipynb
ruff format notebook.ipynb
Продвинутые сценарии
1. Локальное подавление правил
def deprecated_function():
# ruff: noqa: F401, W292
return 42 # Игнорирует 2 правила
2. Per-file игнорирование
В pyproject.toml:
[tool.ruff.per-file-ignores]
"__init__.py" = ["F401"] # Разрешить неиспользуемые импорты в __init__.py
"tests/*.py" = ["S101"] # Разрешить assert в тестах
3. Пользовательские правила
Через плагины (требуется сборка из исходников):
// ruff/src/rules/plugin_example.rs
fn rule_impl(context: &mut Context) -> Option<Diagnostic> {
// Кастомная логика
}
4. Интеграция с pre-commit
.pre-commit-config.yaml:
repos:
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.3.4
hooks:
- id: ruff
args: [--fix, --show-fixes]
- id: ruff-format
Бенчмарки производительности
Тест на кодовой базе Django (20k+ LOC):
| Tool | Time | Rules |
|---|---|---|
| flake8 + isort | 8.2s | 65 |
| Ruff | 0.4s | 188 |
Причины скорости:
- Компиляция в нативный код (Rust)
- Параллельная обработка файлов
- Оптимизированные алгоритмы
Экосистема Ruff
- ruff-lsp — Language Server Protocol
- ruff-pre-commit — интеграция с Git hooks
- Ruff VS Code Extension — расширение для редактора
- Red Hat OpenShift — встроенная поддержка в платформе
Ограничения
- Форматирование пока в бета-версии (не 100% совместимость с black)
- Меньше кастомизации стиля, чем у pylint
- Нет поддержки плагинов из коробки (только через сборку)
Миграция с других инструментов
Пошаговая миграция:
- Заменить isort:
ruff check --select I --fix - Заменить flake8:
ruff check --select E,F,W --fix - Заменить black:
ruff format - Настроить конфиг через
pyproject.toml
Сравнение команд:
| Legacy | Ruff Equivalent |
|---|---|
isort . | ruff check --select I --fix |
flake8 . | ruff check --select E,F,W |
black . | ruff format |
pylint --disable=C | ruff check --ignore PLC |
Пример полного рабочего процесса
- Инициализация проекта:
mkdir myproject && cd myproject
python -m venv .venv
source .venv/bin/activate
- Настройка:
echo "[tool.ruff]" > pyproject.toml
echo "line-length = 88" >> pyproject.toml
- Пример кода (
main.py):
import sys, os # Ошибки: I001, F401
def calculate():
x=2+3 # Ошибка: E225
return {'a':1,'a':2} # Ошибка: F601
- Запуск проверки:
ruff check .
# main.py:1:8: F401 [*] `os` imported but unused
# main.py:1:1: I001 [*] Import block is un-sorted or un-formatted
# main.py:3:16: E225 [*] Missing whitespace around operator
# main.py:4:18: F601 [*] Duplicate key `'a'` in dictionary
- Автоматическое исправление:
ruff check --fix .
Исправленный код:
import sys
def calculate():
x = 2 + 3
return {"a": 2}
Заключение
Ruff — не просто ещё один инструмент, а качественный скачок в инструментарии Python:
- ⚡ Экономия времени — проверка 10k строк за 0.1 сек
- Упрощение стека — один инструмент вместо 5-7
- 🔧 Легкая миграция — совместимость с существующими конфигами
- 🌱 Активное развитие — 20k+ звёзд на GitHub, поддержка PSF
Когда использовать:
- Новые проекты — сразу начать с Ruff
- Существующие проекты — постепенная миграция
- CI/CD пайплайны — ускорение сборок
- Образовательные проекты — минимум настройки
Рекомендации:
- Начните с
ruff check --fix - Постепенно настраивайте правила через
select/ignore - Включите форматирование в pre-commit
- Используйте
ruff formatвместо black
# Оптимальная стартовая команда
ruff check --fix --show-source --ignore=E501 .
Ruff задаёт новый стандарт инструментов Python, делая поддержку кода не обязанностью, а удовольствием.