Python: Линтер
Мы уже научились писать простые программы, и поэтому можно немного поговорить о том, как писать их правильно.
Код нужно оформлять определенным образом, чтобы он был понятным и простым в поддержке. Существуют специальные наборы правил, которые описывают различные аспекты написания кода — их называют стандартами кодирования. В Python стандарт один — PEP8. Он отвечает практически на все вопросы о том, как оформлять ту или иную часть кода. Этот документ содержит все правила, которых нужно придерживаться. Новичкам мы советуем завести привычку заглядывать в стандарт PEP8 и писать код по нему.
Сегодня не нужно помнить все правила из стандарта, потому что существуют специальные программы, которые проверяют код автоматически и сообщают о нарушениях. Такие программы называются линтерами. Они проверяют код на соответствие стандартам. В Python их достаточно много, и наиболее популярный из них — flake8.
Взгляните на пример:
result = 1+ 3
Линтер будет ругаться на нарушение правила: E225 missing whitespace around operator. По стандарту, оператор + всегда должен отделяться пробелами от операндов.
Выше мы увидели правило E225 — это одно из большого количества правил. Другие правила описывают отступы, названия, скобки, математические операции, длину строчек и множество иных аспектов. Каждое отдельное правило кажется неважным и мелким, но вместе они составляют основу хорошего кода. Список всех правил flake8 доступен в этой документации.
Вы уже знакомы с линтером, потому что в практических заданиях платформа Хекслета проверяет ваш код с помощью него. Скоро вы начнете использовать его и за пределами Хекслета, когда будете реализовывать учебные проекты. Вы настроите линтер, и он будет проверять код уже в реальной разработке и сообщать вам о нарушениях.
Задание
Выведите на экран результат следующего вычисления: «разница между пятью в квадрате и произведением трёх и семи». Напишите код так, чтобы каждый оператор отделялся от операндов пробелами.
Упражнение не проходит проверку — что делать?
Если вы зашли в тупик, то самое время задать вопрос в «Обсуждениях». Как правильно задать вопрос:
- Обязательно приложите вывод тестов, без него практически невозможно понять что не так, даже если вы покажете свой код. Программисты плохо исполняют код в голове, но по полученной ошибке почти всегда понятно, куда смотреть.
В моей среде код работает, а здесь нет
Тесты устроены таким образом, что они проверяют решение разными способами и на разных данных. Часто решение работает с одними входными данными, но не работает с другими. Чтобы разобраться с этим моментом, изучите вкладку «Тесты» и внимательно посмотрите на вывод ошибок, в котором есть подсказки.
Мой код отличается от решения учителя
Это нормально , в программировании одну задачу можно выполнить множеством способов. Если ваш код прошел проверку, то он соответствует условиям задачи.
В редких случаях бывает, что решение подогнано под тесты, но это видно сразу.
Прочитал урок — ничего не понятно
Создавать обучающие материалы, понятные для всех без исключения, довольно сложно. Мы очень стараемся, но всегда есть что улучшать. Если вы встретили материал, который вам непонятен, опишите проблему в «Обсуждениях». Идеально, если вы сформулируете непонятные моменты в виде вопросов. Обычно нам нужно несколько дней для внесения правок.
Кстати, вы тоже можете участвовать в улучшении курсов: внизу есть ссылка на исходный код уроков, который можно править прямо из браузера.
Линтер ES Lint
ESLint — это инструмент, помогающий анализировать написанный на JavaScript код, находить синтаксические ошибки и автоматически их исправлять, писать аккуратный код в едином стиле по определённым правилам.
ESLint в терминале
Если у вас пока нет ESLint, его нужно установить из npm.
Давайте испытаем ESLint в действии. Попробуем написать простую функцию для вывода суммы двух чисел и с помощью ESLint проверить правильность написанного кода. Для это в терминале выполним команду
npm run lint
ESLint показывает, что нашёл 6 ошибок в файле main.js . Цифры слева говорят на какой строке, на каком символе, была найдена ошибка. Дальше в строке идёт описание ошибки. Например:

Текст 5 errors and 0 warnings potentially fixable with the —fix option после списка ошибок говорит о том, что пять из шести найденных ошибок ESLint сможет исправить автоматически.
Обратите внимание, что требования, по которым ESLint проверяет код, на каждом проекте могут быть свои, всё зависит от правил, принятых в команде. Например, в команде может быть принято использование двойных кавычек, в таком случае ESLint не будет ругаться на двойные кавычки, а вот при использовании одинарных возникнет ошибка. Такие правила описываются в специальном файле .eslintrc .
Исправление ошибок
Для исправления ошибок у ESLint есть опция fix . Чтобы воспользоваться этой опцией, выполним в терминале команду
npm run lint -- --fix
Ключ —fix говорит о том, что мы хотим исправить ошибки автоматически, а два подчёркивания — перед ключом помогают понять терминалу, что ключ относится не к команде npm run lint , а к тому, что за ней скрывается — к eslint .
ESLint исправил 5 ошибок: поправил пробелы, заменил кавычки на одинарные, удалил ненужную точку с запятой — теперь код выглядит чище. Осталось вызвать функцию, чтобы исправить последнюю ошибку. Здесь ESLint нам не поможет.

ESLint в редакторе
А что, если нам хочется сразу, в момент написания кода, знать, какие ошибки мы совершаем, и исправлять их на лету? Для этого в редактор можно установить расширение для ESLint, которое будет подсвечивать найденную ошибку прямо в файле, а при наведении подсказывать, в чём именно ошибка.
Установка расширения для ESLint в VS Code
Расширение для ESLint в VS Code может попросить подтвердить его запуск, если пакет eslint установлен локально (наш случай). Когда расширение спросит, откуда брать пакет eslint , нужно нажать «Allow», чтобы разрешить использовать eslint в текущем проекте.

С помощью расширения для ESLint в редакторе можно автоматически исправить ошибки. Для этого нужно навести на подсвеченную ошибку, нажать кнопку Quick fix во всплывающем окошке и выбрать один из предложенных вариантов. Например, можно исправить только конкретную ошибку, а можно и все доступные разом. Если ошибка не может быть автоматически исправлена, вместо кнопки Quick fix появится текст No quick fixes available или будут предложены альтернативные варианты решения.
Установка расширения для ESLint в Atom
В Atom тоже требуется специальное расширение linter-eslint для работы ESLint. Чтобы в Atom установить расширение, нужно перейти в раздел настроек «Install Packages». Открыть его можно из окна команд (сочетание клавиш Ctrl + Shift + P на Windows и Command + Shift + P на macOS), введя в поиске «Install Packages».
Также нужный раздел настроек можно открыть через меню: Edit → Preferences → Install — на Windows, Atom → Preferences → Install — в macOS.

Далее ищем нужное расширение и устанавливаем его:

После установки расширения может появиться всплывающее окно с предложением установить нужные зависимости, то есть другие расширения, с помощью которых работает linter-eslint . Для правильной работы линтера нужно установить все предложенные зависимости.

Теперь можно приступить к исправлению ошибок, исправить большинство ошибок можно автоматически, наведя на ошибку и нажав «Fix» или снова использовать окно команд, где выполнить Linter Eslint: Fix File .
Включение поддержки ESLint в WebStorm
В WebStorm не нужно устанавливать отдельное расширение, ESLint работает в этом редакторе «из коробки», достаточно только включить поддержку ESLint. Откройте окно Preferences с настройками, перейдите на вкладку ESLint (Languages and Frameworks → JavaScript → Code Quality Tools → ESLint) и выберете автоматическую конфигурацию ESLint — Automatic ESLint configuration. При автоматической конфигурации ESLint всегда будет искать в директории проекта файл .eslintrc с правилами оформления кода и ориентироваться на него.
Исправляются ошибки так же просто, достаточно нажать правой кнопкой мыши в файле с ошибками и выбрать из списка «Fix ESLint problems».
«Доктайп» — журнал о фронтенде. Читайте, слушайте и учитесь с нами.
Линтинг — Python: Настройка окружения
У кода есть множество разных характеристик, по которым можно судить, насколько хорошо он написан. Среди них есть одна базовая, с которой начинают все разработчики — это стиль написания.
Сравните два варианта оформления кода:
## Без форматирования def find_sum(a,b): c = a+b; return c ## С форматированием def find_sum(a, b): sum = a + b return sum
Второй вариант читается значительно проще. Чем больше будет кода, тем больше будет различий. Хороший стиль кодирования — базовое требование к коду в коммерческой разработке, потому что он упрощает командную разработку. В одном проекте может работать несколько десятков программистов. Важно, чтобы им было легко читать код друг друга, не спотыкаясь о неправильное форматирование.
Для отслеживания подобных ситуаций существуют линтеры — особый класс программ. Линтеры содержат большое количество правил, по которым они могут выдать рекомендации по коду. Другими словами, они подсказывают, как стоит писать код, а как — не стоит. Более того, часто линтеры расширяются плагинами под конкретные фреймворки, что позволяет отслеживать специфичные ошибки и давать рекомендации по кодированию в этих фреймворках.
В Python особой популярностью пользуется линтер flake8 . Количество правил, по которым он проверяет код, исчисляется десятками . Посмотрите на этот небольшой участок кода:
from math import sqrt def sum(a, b): c = 5 return a + b
С точки зрения форматирования здесь все хорошо, а что скажет линтер flake8?
Он выдаст два предупреждения:
- F401 ‘math.sqrt’ imported but unused . Модуль импортируется, но не используется — либо он не нужен, либо в коде есть ошибка
- F841 local variable ‘c’ is assigned to but never used . Переменная не используется — либо она не нужна, либо в коде ошибка
Ссылки выше ведут на страницы конкретных правил. Там подробно объясняется, почему так код писать не нужно. Изучать правила flake8 очень полезно, они прививают хорошие практики написания кода.
Установка и настройка flake8
Линтер flake8 устанавливается как dev зависимость прямо в проект:
--group=dev flake8
После установки его можно настроить под набор ваших правил и ограничений. Для этого нужно создать файл конфигурации setup.cfg, который нужно добавить в репозиторий. Ниже пример такого файла, который используется для настройки линтера в наших практиках:
Выше настраивается максимальная сложность функций, максимальная длина строчки кода и другие параметры. Так же мы можем указать, какие файлы не нужно проверять линтером или какие правила можно игнорировать. Список всех опций вы можете изучить в документации .
И последний шаг — запуск flake8:
# Обратите внимание на точку # Это указание текущей директории и всех поддиректорий poetry run flake8 .
Открыть доступ
Курсы программирования для новичков и опытных разработчиков. Начните обучение бесплатно
- 130 курсов, 2000+ часов теории
- 1000 практических заданий в браузере
- 360 000 студентов
Наши выпускники работают в компаниях:
golangci-lint и внедрение его в большой проект
Хороший разработчик обычно стремится написать код, который не просто работает, но работает стабильно. Код, который легко читать и сопровождать. Достичь такого высокого качества кода кроме тестов также помогают единый стиль кода, хорошая документация, а также простота и изящность, как на уровне всей системы, так и на уровне отдельных модулей и функций.
Считается, что соответствие кода принятым в команде стандартам качества проверяет как сам разработчик, так и его коллеги на код-ревью. Проблема только в том, что все мы люди, и всегда можем что-то упустить. А иногда (на самом деле очень часто), разработчики закрывают глаза на те моменты, которые кажутся им незначительными. В связи с этим придумали статический анализ кода. Если говорить просто, это анализ исходного кода без непосредственного запуска этого кода. Когда вы пробегаете глазами по коду, чтобы убедиться, что с ним всё ок — это тоже статический анализ . Противоположный подход — динамический анализ — предполагает, что код будет запускаться и анализироваться во время исполнения. Примером динамического анализа кода являются тесты, но о них поговорим в другой раз.
Обычно статический анализ строится на основе набора правил, например:
- Длина строки не должна превышать 120 символов;
- Нельзя вызывать defer внутри for ;
- и т.д.
Программы, которые выполняют статический анализ, называют линтерами. Для Go написано уже очень много линтеров, каждый из которых специализируется на своём наборе проверок. Например, bodyclose проверяет, что разработчик не забыл закрыть тело ответа при отправке HTTP-запросов:
internal/httpclient/httpclient.go:13:13: response body must be closed
А wsl следит за тем, чтобы в коде были правильно расставлены пустые строки для повышения читаемости.
Линтеров для Go настолько много, что управлять всеми ими самостоятельно стало в один момент сложнее, чем проверять программы вручную. Поэтому следующим этапом стало появление металинтеров — программ, которые позволяют настроить и запустить большое количество линтеров из единого места. Одним из таких является golangci-lint .
Установка#
golangci-lint можно установить как с помощью привычных пакетных менеджеров, так и с помощью go install . Однако авторы рекомендуют всё-таки ставить с помощью пакетного менеджера.
Быстрый старт#
После установки можно сразу пользоваться программой, используя настройки по умолчанию:
golangci-lint run
golangci-lint run ./.
./. означает, что линтер отработает на файлах в текущей директории, а также рекурсивно на всех файлах во всех подпапках текущей директории.
Настройка#
У golangci-lint хорошая конфигурация по умолчанию, однако она может подойти не для всех проектов. Поэтому можно положить кастомный конфиг-файл .golangci.yml в папку, откуда вы запускаете golangci-lint или явно передать путь до файла:
golangci-lint run ./. --config=./.golangci.yml
Сам конфигурационный файл может выглядеть примерно вот так:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
# Options for analysis running. run: # The default concurrency value is the number of available CPU. concurrency: 4 # Timeout for analysis, e.g. 30s, 5m. # Default: 1m timeout: 5m # Exit code when at least one issue was found. # Default: 1 issues-exit-code: 2 # Include test files or not. # Default: true tests: false # List of build tags, all linters use it. # Default: []. build-tags: - mytag # Which dirs to skip: issues from them won't be reported. # Can use regexp here: `generated.*`, regexp is applied on full path. # Default value is empty list, # but default dirs are skipped independently of this option's value (see skip-dirs-use-default). # "/" will be replaced by current OS file path separator to properly work on Windows. skip-dirs: - src/external_libs - autogenerated_by_my_lib # Enables skipping of directories: # - vendor$, third_party$, testdata$, examples$, Godeps$, builtin$ # Default: true skip-dirs-use-default: false # Which files to skip: they will be analyzed, but issues from them won't be reported. # Default value is empty list, # but there is no need to include all autogenerated files, # we confidently recognize autogenerated files. # If it's not please let us know. # "/" will be replaced by current OS file path separator to properly work on Windows. skip-files: - ".*\\.my\\.go$" - lib/bad.go # If set we pass it to "go list -mod=". From "go help modules": # If invoked with -mod=readonly, the go command is disallowed from the implicit # automatic updating of go.mod described above. Instead, it fails when any changes # to go.mod are needed. This setting is most useful to check that go.mod does # not need updates, such as in a continuous integration and testing system. # If invoked with -mod=vendor, the go command assumes that the vendor # directory holds the correct copies of dependencies and ignores # the dependency descriptions in go.mod. # # Allowed values: readonly|vendor|mod # By default, it isn't set. modules-download-mode: readonly # Allow multiple parallel golangci-lint instances running. # If false (default) - golangci-lint acquires file lock on start. allow-parallel-runners: false # Define the Go version limit. # Mainly related to generics support in go1.18. # Default: use Go version from the go.mod file, fallback on the env var `GOVERSION`, fallback on 1.17 go: '1.18'
Чаще всего будете редактировать конфиг в следующих ситуациях:
- Нужно выключить определённую проверку;
- Нужно добавить или убрать линтер;
- Нужно задать настройки для конкретного линтера;
- Нужно исключить файл или папку из анализа.
Давайте разберёмся с данными кейсами по порядку.
Выключение проверки#
golangci-lint позволяет исключить правила из вывода по шаблону. Например, многие команды отказываются от обязательного комментирования экспортируемых (т.е. публичных) типов, методов, полей, переменных и т.д. Отключить проверку на наличие комментария можно, добавив в конфиге в секцию issues.exclude регулярное выражение, которому соответствует сообщению от линтера:
1 2 3 4 5
# . issues: exclude: - "(comment on exported (method|function|type|const)|should have( a package)? comment|comment should be of the form)" # .
Либо включить исключения по умолчанию, если данная опция была принудительно выключена, т.к. данное исключение уже есть в наборе из коробки: