Инструменты для анализа кода Python. Часть 2
Популярные инструменты для анализа кода Python делают плоды вашего труда лучше и эффективнее. Как? Рассказываем в статье.
Автор: Валерий Шагур, teacher assistance на курсе Программирование на Python
Продолжаем разговор об инструментах для анализа кода Python, начатый нами в первой части статьи.
Flake8
Flake8 — первая программа в этом обзоре, представляющая собой “комбайн”, обвязку к входящим в нее утилитам — pyflakes, pycodestyle, mccabe. В начале работы с ней нас ждал один неприятный сюрприз. Дело в том, что текущая версия flake8-3.2.1 не заработала с текущей версией pycodestyle-2.4.0 и мы были вынуждены откатить pycodestyle до 2.3.1. Этот момент стоит учитывать, если вы в дальнейшем планируете использовать flake8 в своей работе или захотите поэкспериментировать с ней.
Flake8 имеет схожий с pylint основной функционал. Однако она имеет ряд отличий и особенностей:
— Возможности статистических отчетов ограничены подсчетом количества каждой из ошибок (--statistics) и их общим количеством (--count). Пример запуска flake8 на тестовом скрипте:
$ python3.6 -m flake8 --statistics --count example.py example.py:1:1: F401 'os' imported but unused example.py:4:1: E302 expected 2 blank lines, found 1 example.py:4:5: N802 function name 'Function' should be lowercase example.py:4:17: E231 missing whitespace after ',' example.py:7:1: E302 expected 2 blank lines, found 1 example.py:10:22: E231 missing whitespace after ',' example.py:11:17: E225 missing whitespace around operator example.py:13:9: N805 first argument of a method should be named 'self' 1 E225 missing whitespace around operator 2 E231 missing whitespace after ',' 2 E302 expected 2 blank lines, found 1 1 F401 'os' imported but unused 1 N802 function name 'Function' should be lowercase 1 N805 first argument of a method should be named 'self' 8
— Для запуска в несколько потоков (--jobs=<num>) используется модуль multiprocessing, по этой причине многопоточность не будет работать на Windows системах.
— Отсутствует возможность генерации отчетов в формате json, при вызове с ключом --bug-report создается только заголовок для отчета с указанием платформы и версий входящих утилит.
— Комментарии в коде блокирующие вывод. Добавление в строку с ошибкой комментария # noqa, уберет ее из отчета.
— Во время редактирования для подавления отдельных ошибок “на лету” можно перечислить исключаемые ошибки в ключе --extend-ignore=<errors>
— Проверка синтаксиса в строках doctest (--doctests).
Следующие возможности Flake8 можно отнести к его достоинствам. Наличие их сделало Flake8 весьма популярным инструментом среди разработчиков:
— Наличие Version Control Hooks. Интеграция с системами контроля версий происходит буквально с помощью двух команд (поддерживаются git и mercurial). Приведем пример для git. Настройка hook позволяет не допускать создания коммита при нарушении каких-либо правил оформления. Подробнее о механизме git-hook вы можете узнать в документации git.
Инициализируем новый репозиторий в директории с файлом example.py и сделаем первый коммит:
$ git init Инициализирован пустой репозиторий Git в /home/test/.git/ $ git add example.py $ git commit -m "first commit" [master (корневой коммит) d1f25d0] first commit 1 file changed, 20 insertions(+) create mode 100644 example.py
Установим git pre-commit hook:
$ python3.6 -m flake8 --install-hook git git pre-commit hook installed, for configuration options see http://flake8.pycqa.org/en/latest/user/using-hooks.html $ git config --bool flake8.strict true
После этого внесем изменения в файл — добавим комментарий в последнюю строку:
$ echo "# new comment" >> example.py
Попробуем теперь зафиксировать изменения в ветке:
$ git add example.py $ git commit -m "second commit" example.py:1:1: F401 'os' imported but unused example.py:4:1: E302 expected 2 blank lines, found 1 example.py:4:5: N802 function name 'Function' should be lowercase example.py:4:17: E231 missing whitespace after ',' example.py:7:1: E302 expected 2 blank lines, found 1 example.py:10:22: E231 missing whitespace after ',' example.py:11:17: E225 missing whitespace around operator example.py:13:9: N805 first argument of a method should be named 'self'
Вывод содержит только информацию о найденных ошибках, сообщения о зафиксированных изменениях нет. В том, что коммит не был сделан, можно убедиться с помощью команды git status:
$ git status На ветке master Изменения, которые будут включены в коммит: (используйте «git reset HEAD <файл>…», чтобы убрать из индекса) изменено: example.py
— Расширяемость. Flake8 для анализа кода Python позволяет создавать и использовать плагины. С помощью плагинов в Flake8 можно: добавить дополнительные проверки, использовать другие форматы отчетов или автоматически исправлять найденные ошибки. На PyPi можно найти большое количество open-source плагинов.
— В состав Flake8 входит mccabe — инструмент для проверки цикломатической сложности кода.
Prospector
Prospector — это инструмент для анализа кода Python. Объединяет функциональность других инструментов анализа Python, таких как pylint, pep8, mccabe, Pyflakes, Dodgy, pydocstyle (экспериментально, возможны ошибки). Дополнительно можно подключить mypy, pyroma, vulture. Главной особенностью prospector является наличие предустановленных профилей, которые содержат настройки входящих в него утилит, призванных подавить наиболее придирчивые предупреждения и оставить только важные сообщения. Это позволяет начать работу с prospector без длительной настройки. Часть профилей отличаются уровнем “строгости” к требованиям. Из коробки доступно пять таких профилей: verylow, low, medium, high и veryhigh. Для указания этих профилей при запуске анализатора предназначен ключ --strictness:
$ python3.6 -m prospector --strictness veryhigh Messages ======== example.py Line: 1 pylint: unused-import / Unused import os Line: 2 pylint: import-error / Unable to import 'notexistmodule' Line: 4 pep8: N802 / function name 'Function' should be lowercase (col 5) pep8: E302 / expected 2 blank lines, found 1 (col 1) pylint: unused-argument / Unused argument 'num_two' (col 17) pep8: E231 / missing whitespace after ',' (col 17) pylint: invalid-name / Function name "Function" doesn't conform to snake_case naming style Line: 7 pep8: E302 / expected 2 blank lines, found 1 (col 1) pylint: too-few-public-methods / Too few public methods (1/2) Line: 10 pep8: E231 / missing whitespace after ',' (col 22) Line: 11 pep8: E225 / missing whitespace around operator (col 17) Line: 13 pep8: N805 / first argument of a method should be named 'self' (col 9) pylint: no-self-argument / Method should have "self" as first argument (col 4) Line: 18 pylint: invalid-name / Constant name "my_class" doesn't conform to UPPER_CASE naming style (col 4) Line: 19 pylint: too-many-function-args / Too many positional arguments for method call (col 4) Check Information ================= Started: 2018-10-01 22:52:45.294446 Finished: 2018-10-01 22:52:45.567646 Time Taken: 0.27 seconds Formatter: grouped Profiles: default, strictness_veryhigh, no_doc_warnings, no_test_warnings, no_member_warnings Strictness: veryhigh Libraries Used: Tools Run: dodgy, mccabe, pep8, profile-validator, pyflakes, pylint Messages Found: 15
Оставшиеся профили касаются стилистики исходного кода. Полный список можно посмотреть здесь.
Пользователям предоставляется возможность создать профиль под собственные требования. Для хранения настроек профиля используется yaml-файл, что позволяет очень гибко настроить Prospector. Например, определить какие инструменты и с какими настройками использовать, выбрать формат вывода (yaml, text, json, xunit, pylint) и так далее.
В набор утилит Prospector входят три утилиты для анализа кода Python, с которыми мы еще не встречались:
- dodgy — осуществляет поиск секретных ключей, паролей, оставленных разработчиками в исходном коде;
- pyroma — проверяет правильность сборки пакетов;
- mypy — инструмент для проверки типов.
Мы не будем останавливаться на них, так как они выходят за рамки рассматриваемой темы.
Еще одной важной особенностью Prospector, является определение зависимостей. Программа попытается установить, какие библиотеки использует ваш проект и, обнаружив зависимости, автоматически включит поддержку требуемых библиотек.
Pylama
Pylama — инструмент аудита кода для Python и JavaScript. Служит оберткой на такими утилитами как: pydocstyle, pycodestyle, pyflakes, mccabe, pylint, radon (инструмент для сбора и вычисления различных метрик из исходного кода). Для работы с работы с JavaScript кодом используется gjslint.
Из доступных настроек стоит выделить возможность запускаться в асинхронном режиме интеграцию с pytest (пакет автоматически регистрируется как плагин pytest во время установки). Запуск pylama из pytest:
$ python3.6 -m pytest --pylama . ====================== test session starts ================================= platform linux -- Python 3.6.6, pytest-3.8.1, py-1.6.0, pluggy-0.7.1 rootdir: /home/test, inifile: plugins: pylama-7.4.3 collected 1 item example.py F [100%] ======================== FAILURES ====================================== ___________________________________________________________________________ example.py:1:1: W0611 'os' imported but unused [pyflakes] example.py:4:1: E302 expected 2 blank lines, found 1 [pycodestyle] example.py:4:17: E231 missing whitespace after ',' [pycodestyle] example.py:7:1: E302 expected 2 blank lines, found 1 [pycodestyle] example.py:10:22: E231 missing whitespace after ',' [pycodestyle] example.py:11:17: E225 missing whitespace around operator [pycodestyle] -------------------------------------------- Captured stdout call ----------------------------------------------------- example.py:1:1: W0611 'os' imported but unused [pyflakes] example.py:4:1: E302 expected 2 blank lines, found 1 [pycodestyle] example.py:4:17: E231 missing whitespace after ',' [pycodestyle] example.py:7:1: E302 expected 2 blank lines, found 1 [pycodestyle] example.py:10:22: E231 missing whitespace after ',' [pycodestyle] example.py:11:17: E225 missing whitespace around operator [pycodestyle] =========================== 1 failed in 0.20 seconds =========================
autopep8
Рассмотрение форматировщиков в этом обзоре мы начнем с autopep8. Он модифицирует код, не совместимый с PEP8. Проверка соответствия соглашениям осуществляется с помощью утилиты pycodestyle. В autopep8 есть поддержка многопоточности, рекурсивного обхода каталогов, возможность сохранения настроек в файле, задание диапазона строк для исправления, фильтрация ошибок и непосредственное изменение проверяемого файла. По умолчанию программа выводит исправленный код в виде текста на консоль. При использовании ключа --diff выводятся только различия:
$ python3.6 -m autopep8 --diff example.py --- original/example.py +++ fixed/example.py @@ -1,14 +1,16 @@ import os import notexistmodule -def Function(num,num_two): + +def Function(num, num_two): return num + class MyClass: """class MyClass """ - def __init__(self,var): - self.var=var + def __init__(self, var): + self.var = var def out(var): print(var)
autopep8 отлично справляется задачей форматирования, следя за несоблюдением PEP8. Однако невозможность подключения собственных стилей ограничивает круг его применения.
yapf
Код этой утилиты для анализа кода Python принадлежит компании Google. Прежде чем устанавливать этот форматировщик у себя на компьютере, вы можете опробовать yapf в действии с помощью онлайн демонстратора.
По функционалу yapf похож на autopep8, но использует другой подход, который основан на «clang-format», разработанном Дэниелом Джаспером. Отформатированный yapf код, будет не только соблюдать принятые соглашения, но и выглядеть так, словно был написан хорошим программистом. Вторым важным отличием является возможность задавать стили. Для этого воспользуйтесь ключом --style и в качестве аргумента передайте файл с настройками или одно из предопределенных значений (pep8, google, chromium, facebook). Вызов с --style-help покажет текущие настройки, которые можно сохранить в файл и внести необходимые корректировки стиля. Для форматирования отдельных блоков кода в файле, предусмотрен флаг --lines START-END.
black
По утверждению разработчиков, black — это бескомпромиссный форматировщик, который работает быстро и экономит время и умственную энергию программистов для более важных вопросов. Демонстрацию работы black вы можете посмотреть на сайте. При установке программы на компьютер необходимо учитывать, что для запуска black требуется Python версии 3.6 и выше. Также к особенностям данного инструмента можно отнести:
- игнорирование не модифицированных файлов, программа запоминает, какие файлы она изменяла и при следующем запуске форматирует только файлы с внесенными изменениями;
- возможность запретить изменение отдельных блоков в коде, для этого используются комментарии: # fmt: off и # fmt: on, обозначающие начало и конец блока;
- длина строки по умолчанию является 88 символов, что не соответствует официальному соглашению PEP8;
- дополнительно можно установить HTTP сервер blackd, который позволяет избежать накладных расходов на создание процесса каждый раз, когда мы хотим отформатировать файл. Исходный код передается в теле POST запроса, а флаги управления форматированием в заголовках (флаги идентичны ключам командной строки, используемых при запуске black).
Заключение
Мы рассмотрели наиболее известные инструменты для анализа и автоматического форматирования кода. Многие из них давно интегрированы в современные IDE (SiblimeText, PyCharm, VisualStudio) и текстовые редакторы (Vim, Emacs). На основе некоторых построены онлайн-сервисы:
- http://pep8online.com
- http://www.pylintonline.com
- https://www.tutorialspoint.com/online_python_formatter.htm
Существуют и другие инструменты для работы с кодом. Например, утилита для сортировки импорта по алфавиту и автоматического разделения на разделы — isort или библиотека ciocheck. Формат статьи не позволяет включить их все в обзор. Тем не менее мы уверены, что использования даже некоторых из рассмотренных выше инструментов достаточно для того, чтобы повысить качество кода в вашем проекте, сделать более комфортным совместную работу и в некоторых случаях избежать ошибок.
ФРОО рекомендует:
До конца октября действует промокод backupmaster, который дает скидку 5000 рублей на курс Программирование на Python и 5000 рублей на курс Машинное обучение и анализ данных.