Инструменты для анализа кода 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). На основе некоторых построены онлайн-сервисы:

Существуют и другие инструменты для работы с кодом. Например, утилита для сортировки импорта по алфавиту и автоматического разделения на разделы — isort или библиотека ciocheck. Формат статьи не позволяет включить их все в обзор. Тем не менее мы уверены, что использования даже некоторых из рассмотренных выше инструментов достаточно для того, чтобы повысить качество кода в вашем проекте, сделать более комфортным совместную работу и в некоторых случаях избежать ошибок.

ФРОО рекомендует:
До конца октября действует промокод backupmaster, который дает скидку 5000 рублей на курс Программирование на Python и 5000 рублей на курс Машинное обучение и анализ данных.

Еще статьи по Python

ЛУЧШИЕ СТАТЬИ ПО ТЕМЕ

admin
11 декабря 2018

ООП на Python: концепции, принципы и примеры реализации

Программирование на Python допускает различные методологии, но в его основе...
admin
28 июня 2018

3 самых важных сферы применения Python: возможности языка

Существует множество областей применения Python, но в некоторых он особенно...
admin
13 февраля 2017

Программирование на Python: от новичка до профессионала

Пошаговая инструкция для всех, кто хочет изучить программирование на Python...