В мире Python-разработки поддержка чистоты кода критически важна. Традиционно для этого используются:
- Линтеры (flake8, pylint) — анализ ошибок и стиля
- Форматтеры (black, autopep8) — автоматическое форматирование
- Инструменты сортировки импортов (isort)
Проблема: Множество инструментов = сложная настройка + медленная работа.
Решение: Ruff — инструмент на Rust, объединяющий функциональность линтера, форматтера и сортировщика импортов с фокусом на скорости и удобстве.
Ключевые особенности
1. Невероятная скорость (в 10-100 раз быстрее аналогов)
2. 700+ встроенных правил (совместимость с flake8, isort, pyupgrade)
3. Автофикс для 50%+ правил
4. Форматирование кода (альтернатива black)
5. Простая установка — один бинарный файл
6. Современный стандарт — поддержка 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)
1. Установите расширение Ruff
2. Добавьте в 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
Причины скорости:
1. Компиляция в нативный код (Rust)
2. Параллельная обработка файлов
3. Оптимизированные алгоритмы
Экосистема Ruff
1. ruff-lsp — Language Server Protocol
2. ruff-pre-commit — интеграция с Git hooks
3. Ruff VS Code Extension — расширение для редактора
4. Red Hat OpenShift — встроенная поддержка в платформе
Ограничения
1. Форматирование пока в бета-версии (не 100% совместимость с black)
2. Меньше кастомизации стиля, чем у pylint
3. Нет поддержки плагинов из коробки (только через сборку)
Миграция с других инструментов
Пошаговая миграция:
1. Заменить isort: `ruff check --select I --fix`
2. Заменить flake8: `ruff check --select E,F,W --fix`
3. Заменить black: `ruff format`
4. Настроить конфиг через `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
Пример полного рабочего процесса
1. Инициализация проекта:
mkdir myproject && cd myproject
python -m venv .venv
source .venv/bin/activate
2. Настройка:
echo "[tool.ruff]" > pyproject.toml
echo "line-length = 88" >> pyproject.toml
3. Пример кода (`main.py`):
import sys, os # Ошибки: I001, F401
def calculate():
....x=2+3 # Ошибка: E225
....return {'a':1,'a':2} # Ошибка: F601
4. Запуск проверки:
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
5. Автоматическое исправление:
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 пайплайны — ускорение сборок
- Образовательные проекты — минимум настройки
Рекомендации:
1. Начните с `ruff check --fix`
2. Постепенно настраивайте правила через `select/ignore`
3. Включите форматирование в pre-commit
4. Используйте `ruff format` вместо black
# Оптимальная стартовая команда
ruff check --fix --show-source --ignore=E501 .
Ruff задаёт новый стандарт инструментов Python, делая поддержку кода не обязанностью, а удовольствием.
Подписывайтесь:
Телеграм https://t.me/lets_go_code
Блог "Просто о программировании" http://lets-go-code.ru/blog/