$ sudo teach|
    $ sudo teach|
    IT school
  • Telegram
  • Партнёрам
  • Все курсы
$ sudo teach IT
OOO "SALEPROFIT"Контакты и реквизитыIT-Park Logo

Школа

  • Блог
  • Проверить сертификат

Сотрудничество

  • Стать учителем
  • Партнёрская программа
  • О проекте

Право

  • Оферта
  • Политика конфиденциальности

© 2023–2026 $ sudo teach IT™. All Rights Reserved. Public user contributions licensed under CC BY-SA 4.0 license with attribution required
TelegramGitHubYouTube
ГлавнаяБлогruff на максималках: правила, исключения и единый стиль команды

ruff на максималках: правила, исключения и единый стиль команды

$ sudo teach IT
·21 июля 2026 г.·10 мин·62
ruff на максималках: правила, исключения и единый стиль команды

Как договориться о правилах, настроить конфиг под реальный код-стайл команды и не спорить о форматировании и линтинге бесконечно.

Содержание
Что именно делает ruff (и почему споры неизбежны без рамок)Стратегия внедрения: “сейчас всё исправим” или “не тормозим разработку”Подход A: жёсткий старт (всё привести в порядок сразу)Подход B: постепенное внедрение (новый код — строго, старый — по остаточному принципу)Структура конфигурации: где ruff хранит правилаПравила и “единый стиль”: как договориться без бесконечных обсуждений1) Определите “уровни строгости”: что считается нарушением процесса2) Не смешивайте “правки стиля” и “правки логики” в одной философии PR3) Настройте line length и импортный стиль так, как принято в командеИсключения: как разрешить конфликты и не превратить их в дыруВарианты исключений1) Исключения на уровне путей: для legacy и generated2) Исключения через noqa: только точечно и с указанием кода3) “Временные” исключения должны иметь срокКак включать правила “с умом”: минимальный шум и максимальная пользу1) Начните с набора, который почти всем полезен2) Затем добавляйте “спорные” правила после того, как люди согласовали формат3) Управляйте прогрессом через CI и pre-commitАвтоисправления и форматирование: как избежать “линтер сломал стиль”Практика: включайте авто-фикс только для того, что действительно согласованоПример: как запускать ruff в режиме проверки и автофиксаpre-commit: единый процесс вместо бесконечной перепискиТиповые ошибки конфигурации (которые почти всегда ломают процесс)Ошибка 1: Нет “источника правды” по конфигуОшибка 2: Слишком широкие per-file-ignoresОшибка 3: noqa без кода и без объясненияОшибка 4: Конфликт line-length / переносов с форматтеромПрактический рецепт: как зафиксировать правила в командеШаг 1: Принять базовый стиль и зафиксировать параметрыШаг 2: Решить, что делать со старым кодомШаг 3: Установить правило для исключенийШаг 4: Автоматизировать локальный процесс и CIШаг 5: Проводить ежемесячную ревизию качества конфигурацииВывод: ruff становится “контрактом”, когда правила оформлены в конфиг и процесс

Договориться о код-стайле в команде — это всегда про нечто большее, чем “нравится/не нравится”. В реальности споры обычно крутятся вокруг форматирования, переносов, порядка импортов, именования, и особенно вокруг того, кто и как должен “править линтером” — вручную или автоматически, и почему линтер ругается именно на этот кейс.

ruff — один из самых практичных инструментов для наведения порядка в Python-проектах: он быстрый, покрывает много правил, поддерживает конфигурацию исключений и позволяет выстроить единый стиль. Но “поставить ruff и забыть” не работает: без продуманной конфигурации и правил изменений вы получите либо бессмысленный шум, либо бесконечные обсуждения на тему “линтер неправ”.

Эта статья — про то, как договориться о правилах, настроить конфиг под реальный код-стайл команды и минимизировать споры. Мы разберём практические подходы, типовые ошибки и рабочие примеры конфигурации. По ходу я аккуратно упомяну курс ruff – для начинающих! — как один из способов быстро подтянуть базу.


Что именно делает ruff (и почему споры неизбежны без рамок)

ruff — это статический анализатор, который объединяет множество правил из экосистемы линтинга: flake8-подобные проверки, pycodestyle/pyflakes, isort-логика, некоторые правила из других источников и собственные проверки. На практике ruff решает две задачи:

  1. Правила стиля/качества (например, “не используй import *”, “не дублируй импорт”, “не допускай неиспользуемые переменные”).
  2. Авто-форматирование/авто-исправления (часть правил умеет править код через ruff check --fix или ruff format — в зависимости от типа проблемы и настроек).

Когда команда не согласовала, что именно считать ошибкой, предупреждением и чем допустимо пренебречь ради “наследия” — начинаются споры. Часть участников считает всё, что ругается, “ошибка разработки”. Другая часть — “пусть линтер подстроится под проект”.

Поэтому основная идея — не искать “идеальные правила”, а построить систему договорённостей, где:

  • правила имеют статус (ошибка/предупреждение);
  • часть правил включается “с нуля”, часть — только на новый код;
  • есть механизм исключений без злоупотреблений;
  • есть воспроизводимость: одинаковая конфигурация и одинаковые версии на всех машинах/CI.

Стратегия внедрения: “сейчас всё исправим” или “не тормозим разработку”

Первый практический выбор — как заходить в проект.

Подход A: жёсткий старт (всё привести в порядок сразу)

Плюсы: меньше долгосрочного техдолга, проще поддерживать единый стиль.
Минусы: может потребоваться большой PR, сложнее провести релиз без пауз.

Этот подход оправдан, когда:

  • кодовая база относительно свежая;
  • команда может выделить время на “купол качества” (например, один спринт);
  • правило уже не вызывает концептуальных разногласий.

Подход B: постепенное внедрение (новый код — строго, старый — по остаточному принципу)

Плюсы: минимальные изменения в текущей кодовой базе, меньше конфликтов.
Минусы: на протяжении времени есть “двойной стандарт”: новый код под линтер, старый — с послаблениями.

Для большинства команд это реалистичнее. Ключевой механизм — таргетить анализ на конкретный набор путей/файлов или использовать режимы исключений и фильтрации по “типу нарушения”.


Структура конфигурации: где ruff хранит правила

ruff поддерживает конфигурацию через pyproject.toml (чаще всего) или отдельные файлы. Практика для команды — хранить в pyproject.toml, чтобы не разрывать “источник правды”.

Обычно удобно разделить:

  • какие правила включены;
  • какие правила исключены;
  • какие пути игнорируются;
  • какие стилистические настройки применяются (например, стиль импортов).

Ниже — пример каркаса, который потом можно расширять:

code
# pyproject.toml
[tool.ruff]
target-version = "py311"
line-length = 100

# По умолчанию ruff будет анализировать исходники в проекте
# (конкретный набор можно уточнять через include/exclude).
exclude = [
  ".git",
  ".venv",
  "build",
  "dist",
]

[tool.ruff.lint]
# Выберите режимы: правила и severity.
# Ниже покажем подход “набор правил + исключения”.

Правила и “единый стиль”: как договориться без бесконечных обсуждений

Теперь — самый важный блок. Договорённость не должна быть “в голове”. Её нужно превратить в конфигурацию и правила работы команды.

1) Определите “уровни строгости”: что считается нарушением процесса

Частая ошибка — включить максимум правил и оставить всем свободу трактовки. Итог: линтер начинает конфликтовать с реальным темпом разработки.

Вместо этого стоит договориться о матрице:

  • Ошибки (must-fix): правила, нарушающие корректность или явно указывающие на проблемы (например, неиспользуемые переменные, неправильные импорты, потенциальные ошибки).
  • Предупреждения (should-fix): правила стиля/качества, которые полезны, но не должны стопорить каждую правку.
  • Игнор/исключения: то, что невозможно/дорого исправить прямо сейчас или что конфликтует с архитектурными решениями проекта.

ruff позволяет управлять тем, какие правила включены, и настраивать наборы ошибок через селекты/айклюды (в зависимости от версии ruff и типа правил). На практике часто делают так: сначала включают популярные группы, затем точечно отключают спорные.

Например, для стартового “разумного максимума” команда может включить:

  • базовые проверки из flake8/pyflakes-подобных (качество/ошибки);
  • isort-проверки (порядок импортов);
  • часть pycodestyle (синтаксический стиль).

2) Не смешивайте “правки стиля” и “правки логики” в одной философии PR

Если ruff используется и как линтер, и как авто-исправлятор, команда должна договориться, когда это применяется.

Реалистичная схема:

  • PRы по функциональности не должны содержать случайные исправления “форматирования”.
  • если форматирование нужно привести — это отдельный “стилизационный” PR или автоматический шаг в CI/pre-commit, который применяется прозрачно.

Пакетное применение ruff check --fix может генерировать большие диффы. Поэтому лучше запускать форматирование/исправления предсказуемо (например, pre-commit) и отслеживать, что именно делает автофиксер.

3) Настройте line length и импортный стиль так, как принято в команде

Две причины, почему люди спорят с линтером чаще всего:

  • длина строки и переносы;
  • порядок импортов.

Обе вещи легко зафиксировать.

Например, если команда хочет line-length = 100 и конкретную логику сортировки импортов, это должно жить в конфиге.

code
[tool.ruff]
line-length = 100

[tool.ruff.lint.isort]
# Пример: аккуратно настроить формат
force-wrap-aliases = true
known-first-party = ["your_package"]
known-third-party = ["requests", "numpy"]

Если у вас “и так сортируется как-то” — на практике это приводит к тому, что разные разработчики получают разные диффы. Конфиг должен быть общим.


Исключения: как разрешить конфликты и не превратить их в дыру

Исключения неизбежны: legacy-код, внешние API, генерация кода, специфические паттерны. Важно одно: исключения должны быть управляемыми, ограниченными и объяснимыми.

Варианты исключений

  1. Игнорировать правила для конкретных файлов/путей в конфиге.
  2. Игнорировать конкретные правила в конкретных местах через # noqa: CODE.
  3. Использовать допустимые формы noqa и договориться, когда это разрешено.

1) Исключения на уровне путей: для legacy и generated

Например, если у вас есть автогенерируемые модули:

code
[tool.ruff]
exclude = ["generated/**", ".venv", "build", "dist"]

или более точечно:

code
[tool.ruff.lint]
per-file-ignores = { 
  "generated/**/*.py" = ["ALL"],
  "tests/test_*.py" = ["SOME_RULE_ID"]
}

Подводный камень: per-file-ignores легко превратить в “мы здесь ничего не исправляем”. Поэтому стоит договориться: исключения на тестах — допустимы, но только для конкретных правил и с понятным обоснованием.

2) Исключения через noqa: только точечно и с указанием кода

Наиболее полезная практика — никогда не делать # noqa без кода, если в конфиге много правил. Тогда вы теряете контроль.

Пример:

code
from typing import Any

def f(x: Any) -> Any:
    # noqa: ARG001  (аргумент намеренно не используется)
    return x

Если вы написали # noqa без кода, то ruff “молча проедает” проблему. В команде это часто становится нормой, и качество деградирует незаметно.

3) “Временные” исключения должны иметь срок

Полезная договорённость: если правило отключено из-за миграции или дефицита времени — это должно быть помечено как временное (например, комментом рядом с исключением) и привязано к задаче/тикету. Ruff сам по себе не ведёт историю “временности”, но команда может.


Как включать правила “с умом”: минимальный шум и максимальная пользу

Рассмотрим практическую схему набора правил.

1) Начните с набора, который почти всем полезен

Обычно это:

  • устранение неиспользуемых импортов и переменных;
  • базовые ошибки в коде (аналог pyflakes);
  • изоляция потенциальных проблем;
  • изорт (упорядочивание импортов).

2) Затем добавляйте “спорные” правила после того, как люди согласовали формат

Правила стиля чаще всего конфликтуют с личными привычками. Поэтому лучше:

  • сначала договориться о line length;
  • потом — о размещении импортов;
  • потом — о форматировании (включая правила, которые влияют на автоправки).

Иначе вы получаете эффект: линтер выглядит “непонятным”, потому что он ведёт к диффам по форматированию, которые разработчик не контролирует.

3) Управляйте прогрессом через CI и pre-commit

Один из лучших способов прекратить споры — сделать процесс механическим.

  • разработчик запускает ruff локально (предсказуемо);
  • CI прогоняет тот же набор правил;
  • коммит не проходит, если есть нарушения “must-fix”.

Автоисправления и форматирование: как избежать “линтер сломал стиль”

ruff имеет возможности автоисправления, но важно понимать, что:

  • не все правила исправляются автоматически;
  • некоторые правки влияют на диффы больших файлов;
  • автофиксер может быть не тем, что “ожидает” команда, если конфиг не согласован.

Практика: включайте авто-фикс только для того, что действительно согласовано

Обычно разумный путь:

  • сортировку импортов и простые правки стиля автофиксить можно;
  • сложные правки оставлять на стадию “ручной ревью” — особенно если ruff меняет поведение или структуру.

Пример: как запускать ruff в режиме проверки и автофикса

code
# Проверка
ruff check .

# Автофикс (только те правила, для которых есть fix)
ruff check . --fix

# Если вы используете отдельный форматтер ruff (зависит от версии/конфигурации),
# можно запускать ruff format:
ruff format .

В команде стоит договориться: каким образом правки попадают в PR. Например:

  • “Мы всегда запускаем ruff check --fix перед коммитом”;
  • или “CI всегда форматирует и запрашивает повторный прогон” (но это может быть неудобно).

На практике чаще всего используют pre-commit, чтобы изменения были видны заранее.


pre-commit: единый процесс вместо бесконечной переписки

Чтобы “один стиль на команду” работал, нужно синхронизировать локальные шаги.

Схема такая:

  1. в репозиторий добавляется .pre-commit-config.yaml;
  2. в pre-commit настраиваются хуки ruff (check и fix, по ситуации);
  3. разработчики получают одинаковое поведение локально;
  4. CI совпадает с локальными правилами (или имеет тот же набор).

Пример (упрощённый):

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

Подводные камни:

  • версия ruff в pre-commit должна быть согласована с версией в CI;
  • аргументы (например, --fix) должны соответствовать договорённости команды;
  • если вы не хотите, чтобы pre-commit менял код, уберите --fix и используйте только проверку.

Типовые ошибки конфигурации (которые почти всегда ломают процесс)

Ошибка 1: Нет “источника правды” по конфигу

Если ruff смотрит на разные конфиги в разных местах (или у части разработчиков старый pyproject.toml/не тот каталог), вы получите “у меня не ругается”.

Решение:

  • один конфиг в репозитории;
  • фиксируйте версию ruff (в lock-файлах или в CI/pre-commit).

Ошибка 2: Слишком широкие per-file-ignores

Когда исключения начинаются как “временно”, они быстро разрастаются. В итоге ruff превращается в “проверяет только половину проекта”.

Правильный подход:

  • точечные правила;
  • “ALL” только для generated или строго контролируемых кейсов;
  • регулярная ревизия исключений.

Ошибка 3: noqa без кода и без объяснения

Это подрывает смысл статического анализа.

Правильный подход:

  • указывать код правила;
  • избегать “заглушек” на большие блоки.

Ошибка 4: Конфликт line-length / переносов с форматтером

Если команда использует несколько инструментов, которые по-разному определяют правила форматирования, будут вечные диффы.

Один из принципов: выберите один инструмент как “финальный” для форматирования (или чётко разделите ответственность: например, ruff исправляет импорты и простые вещи, а форматтер — выравнивание/переносы).


Практический рецепт: как зафиксировать правила в команде

Ниже — рабочий “скелет” процесса, который помогает почти всегда.

Шаг 1: Принять базовый стиль и зафиксировать параметры

  • line-length
  • стиль импортов (known-first-party, сортировка)
  • минимальный набор правил (на качество/ошибки и самые полезные стилистические)

Шаг 2: Решить, что делать со старым кодом

  • либо “всё сразу”
  • либо “строго на новый код” + план по миграции (через тикеты и итерации)

Если вы не готовы к миграции, хотя бы убедитесь, что линтер не тормозит разработку: исключите legacy-части на уровне путей.

Шаг 3: Установить правило для исключений

  • noqa только с кодом
  • исключения на файлы только с конкретными правилами
  • запрет на “глушение” целых направлений без причины

Шаг 4: Автоматизировать локальный процесс и CI

  • pre-commit проверяет одинаково
  • CI повторяет те же проверки
  • разработчики не обсуждают форматирование руками — обсуждают только смысл и корректность исключений

Шаг 5: Проводить ежемесячную ревизию качества конфигурации

Раз в месяц “подчищайте”:

  • исключения, которые уже не нужны;
  • правила, которые больше не вызывают споров (можно включать сильнее);
  • места, где люди продолжают добавлять noqa — возможно, там проблема конфигурирования или рефакторинг стоит сделать один раз.

Вывод: ruff становится “контрактом”, когда правила оформлены в конфиг и процесс

ruff можно настроить так, что он будет не предметом споров, а механическим контрактом между разработчиками: что считается нарушением, как именно это измеряется и где допустимы исключения.

Ключ — не пытаться сразу “включить всё на максимум” без договорённостей, а построить:

  • понятный набор правил (и уровни строгости),
  • жёсткую фиксацию параметров стиля,
  • контролируемые исключения,
  • одинаковый запуск локально и в CI.

Если у команды в целом пока мало практики с настройкой

Войдите, чтобы поставить лайк и оставить комментарий.

Автор

$ sudo teach IT

ruff – для начинающих!

Курс по теме

ruff – для начинающих!

С нуля до уверенной работы с линтингом и форматированием Python-кода. Подходит для начинающих и тех, кто уже пишет на Python. Разберитесь с Ruff раз и навсегда — и перестаньте гадать, какой инструмент запускать.

Бесплатно
Открыть курс

Продолжите обучение

Все курсы
Python – для начинающих!

Python – для начинающих!

С нуля до профессионального уровня. Подходит для всех. Учитесь каждый день и овладейте самым популярным языком программирования.

Перейти к курсу
Простыми словами о защищенном соединении

Простыми словами о защищенном соединении

Базовый курс для обычных людей: что такое защищённое соединение, как оно устроено, что оно умеет и чего не умеет, как выбрать сервис и настроить его на своих устройствах.

Перейти к курсу
Ботостроение Telegram

Ботостроение Telegram

Лёгкий, быстрый и доступный способ познакомиться с миром ботостроения в Telegram. Видео, конспекты, практика и помощь – всё у нас на курсе.

Перейти к курсу
Сервис, который не падает - как построить безопасную зашифрованную сеть

Сервис, который не падает - как построить безопасную зашифрованную сеть

Практический курс по безопасности сети: как собрать собственный сервис защищённого доступа - от пустого сервера до подписки с автовыбором - и, что важнее, как потом не уронить его своими руками.

Перейти к курсу

Другие статьи

Запуск и поддержка проекта на Ruff в команде: формат “как в CI”, а не “как договорились”
запуск

Запуск и поддержка проекта на Ruff в команде: формат “как в CI”, а не “как договорились”

Как правильно выстроить конфигурацию Ruff (линтинг, форматирование, автозамены) и сделать так, чтобы одинаковые правила гарантировались в локальной сборке и на CI без ручного шаманства.

16 сентября 2026 г.
1050
Введение в ruff-линтеры для старта: правила, которые быстрее всего окупаются
введение

Введение в ruff-линтеры для старта: правила, которые быстрее всего окупаются

Покажем, какие проверки ruff дают максимальную пользу на первом этапе: лучшие правила для стиля и предотвращения ошибок, как собрать минимальный конфиг и постепенно включать строгие ограничения без остановки разработки.

14 сентября 2026 г.
640
Создание Telegram бота в 2026 легко и просто! Полный курсы!
создание

Создание Telegram бота в 2026 легко и просто! Полный курсы!

19 июня 2026 г.
1431
Как выбрать, куда идти в IT: веб, боты, данные — без хаоса
выбрать

Как выбрать, куда идти в IT: веб, боты, данные — без хаоса

Разберём самые понятные направления для новичка (веб, боты, аналитика/данные) и чем они отличаются по шагам обучения. В конце вы получите простой план, как проверить, что вам подходит, и какой стартовый путь выбрать.

5 октября 2026 г.
580
Путь от README до демо: как собрать портфолио разработчика, чтобы его хотели смотреть
путь

Путь от README до демо: как собрать портфолио разработчика, чтобы его хотели смотреть

Разберём структуру репозитория, как упаковать проект в понятную историю (проблема → решение → запуск → метрики качества) и какие артефакты повышают доверие: скринкасты, архитектурная схема, чек-лист продакшн-готовности.

17 сентября 2026 г.
1090
Как понять, какой язык программирования учить первым: простой тест и выбор
понять

Как понять, какой язык программирования учить первым: простой тест и выбор

Помогу новичку выбрать первый язык без стресса: объясню варианты по целям (веб, боты, анализ данных), что учить в первую очередь и как не потратить месяцы впустую. В конце — краткий план старта на ближайшие недели.

2 октября 2026 г.
630

Комментарии

Станьте первым в обсуждении

Поделитесь мнением о статье или задайте вопрос автору

Содержание

Что именно делает ruff (и почему споры неизбежны без рамок)Стратегия внедрения: “сейчас всё исправим” или “не тормозим разработку”Подход A: жёсткий старт (всё привести в порядок сразу)Подход B: постепенное внедрение (новый код — строго, старый — по остаточному принципу)Структура конфигурации: где ruff хранит правилаПравила и “единый стиль”: как договориться без бесконечных обсуждений1) Определите “уровни строгости”: что считается нарушением процесса2) Не смешивайте “правки стиля” и “правки логики” в одной философии PR3) Настройте line length и импортный стиль так, как принято в командеИсключения: как разрешить конфликты и не превратить их в дыруВарианты исключений1) Исключения на уровне путей: для legacy и generated2) Исключения через noqa: только точечно и с указанием кода3) “Временные” исключения должны иметь срокКак включать правила “с умом”: минимальный шум и максимальная пользу1) Начните с набора, который почти всем полезен2) Затем добавляйте “спорные” правила после того, как люди согласовали формат3) Управляйте прогрессом через CI и pre-commitАвтоисправления и форматирование: как избежать “линтер сломал стиль”Практика: включайте авто-фикс только для того, что действительно согласованоПример: как запускать ruff в режиме проверки и автофиксаpre-commit: единый процесс вместо бесконечной перепискиТиповые ошибки конфигурации (которые почти всегда ломают процесс)Ошибка 1: Нет “источника правды” по конфигуОшибка 2: Слишком широкие per-file-ignoresОшибка 3: noqa без кода и без объясненияОшибка 4: Конфликт line-length / переносов с форматтеромПрактический рецепт: как зафиксировать правила в командеШаг 1: Принять базовый стиль и зафиксировать параметрыШаг 2: Решить, что делать со старым кодомШаг 3: Установить правило для исключенийШаг 4: Автоматизировать локальный процесс и CIШаг 5: Проводить ежемесячную ревизию качества конфигурацииВывод: ruff становится “контрактом”, когда правила оформлены в конфиг и процесс