Анализ кода в Python

Анализ кода в Python может быть трудной темой, но очень полезной в тех случаях, когда вам нужно повысить производительность вашей программы. Существует несколько анализаторов кода для Python, которые вы можете использовать для проверки своего кода и выяснить, соответствует ли он стандартам. Самым популярным можно назвать pylint. Он очень удобен в настойках и подключениях. Он также проверяет ваш код на соответствие с PEP8, официальным руководством по стилю ядра Python, а также ищет программные ошибки. Обратите внимание на то, что pylint проверяет ваш код на большую часть стандартов PEP8, но не на все. Также мы уделим наше внимание тому, чтобы научиться работать с другим анализатором кода, а именно pyflakes.

Начнем с pylint

Пакет pylint не входит в Python, так что вам нужно будет посетить PyPI (Python Package Index), или непосредственно сайт пакета для загрузки. Вы можете использовать следующую команду, которая сделает всю работу за вас:

Если все идет по плану, то pylint установится, и мы сможем пойти дальше.

Анализ вашего кода

После установки pylint вы можете запустить его в командной строке, без каких либо аргументов, что бы увидеть, какие опции он принимает. Если это не сработало, можете прописать полный путь, вот так:

Теперь нам нужен какой-нибудь код для анализа. Вот часть кода, которая содержит четыре ошибки. Сохраните её в файле под названием crummy_code. py:

Можете увидеть ошибки не запуская код? Давайте посмотрим, может ли pylint найти их!

Есть вопросы по Python?

На нашем форуме вы можете задать любой вопрос и получить ответ от всего нашего сообщества!

Telegram Чат & Канал

Вступите в наш дружный чат по Python и начните общение с единомышленниками! Станьте частью большого сообщества!

Паблик VK

Одно из самых больших сообществ по Python в социальной сети ВК. Видео уроки и книги для вас!

После запуска этой команды вы увидите большую выдачу на вашем экране. Вот частичный пример:

Давайте немного притормозим и разберемся. Сначала нам нужно понять, что означают буквы:

  • С – конвенция (convention)
  • R – рефакторинг (refactor)
  • W – предупреждение (warning)
  • E – ошибка (error)

Наш pylint нашел 3 ошибки, 4 проблемы с конвенцией, 2 строки, которые нуждаются в рефакторинге и одно предупреждение. Предупреждение и 3 ошибки – это как раз то, что я искал. Мы попытаемся исправить этот код и устранить ряд проблем. Для начала мы наведем порядок в импортах, и изменить функцию getWeight на get_weight, в связи с тем, что camelCase не используется в названиях методов. Нам также нужно исправить вызов get_weight, чтобы он передавал правильное количество аргументов и исправить его, чтобы “self” выступал в качестве первого аргумента. Взглянем на новый код:

Давайте запустим новый код с pylint и посмотрим, насколько успешно мы провели работу. Для краткости, мы еще раз рассмотрим первую часть:

Как мы видим, это очень помогло. Если мы добавим docstrings, мы можем снизить количество ошибок вдвое. Теперь мы готовы перейти к pyflakes!

Работаем с pyflakes

Проект pyflakes это часть чего-то, что называется Divmod Project. Pyflakes на самом деле не выполняет проверяемый код также, как и pylint. Вы можете установить pyflakes при помощи pip, easy_install, или из другого источника.

Данный сервис может предложить Вам персональные условия при заказе классов на посты и фото в Одноклассники. Приобретайте необходимый ресурс не только со скидками, но и с возможностью подобрать наилучшее качество и скорость поступления.

Мы начнем с запуска pyflakes в изначальной версии той же части кода, которую мы использовали для проверки pylint. Вот и он:

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

Несмотря на суперски быструю скорость возврата выдачи, pyflakes не нашел все ошибки. Вызов метода getWeight передает слишком много аргументов, также метод getWeight сам по себе определен некорректно, так как у него нет аргумента self. Что-же, вы, собственно, можете называть первый аргумент так, как вам угодно, но в конвенции он всегда называется self. Если вы исправили код, оперируя тем, что вам сказал pyflakes, код не заработает, несмотря на это.

Подведем итоги

Следующим шагом должна быть попытка запуска pylint и pyflakes в вашем собственном коде, либо же в пакете Python, вроде SQLAlchemy, после чего следует изучить полученные в выдаче данные. Вы можете многое узнать о своем коде, используя данные инструменты. pylint интегрирован с Wingware, Editra, и PyDev. Некоторые предупреждения pylint могут показаться вам раздражительными, или не особо уместными. Существует несколько способов избавиться от таких моментов, как предупреждения об устаревании, через опции командной строки. Вы также можете использовать -generate-rcfile для создания примера файла config, который поможет вам контролировать работу pylint. Обратите внимание на то, что pylint и pyflakes не импортируют ваш код, так что вам не нужно беспокоиться о нежелательных побочных эффектах.

Являюсь администратором нескольких порталов по обучению языков программирования Python, Golang и Kotlin. В составе небольшой команды единомышленников, мы занимаемся популяризацией языков программирования на русскоязычную аудиторию. Большая часть статей была адаптирована нами на русский язык и распространяется бесплатно.

Значения исключений и ошибок в Python

Распродажа знаний!

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

Синтаксис обработки исключений

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

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

Обработка исключений делает код более отказоустойчивым и помогает предотвращать потенциальные проблемы, которые могут привести к преждевременной остановке выполнения. Представьте код, который готов к развертыванию, но все равно прекращает работу из-за исключения. Клиент такой не примет, поэтому стоит заранее обработать конкретные исключения, чтобы избежать неразберихи.

Ошибки могут быть разных видов:

  • Синтаксические
  • Недостаточно памяти
  • Ошибки рекурсии
  • Исключения

Разберем их по очереди.

Синтаксические ошибки (SyntaxError)

Синтаксические ошибки часто называют ошибками разбора. Они возникают, когда интерпретатор обнаруживает синтаксическую проблему в коде.

Рассмотрим на примере.

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

Недостаточно памяти (OutofMemoryError)

Ошибки памяти чаще всего связаны с оперативной памятью компьютера и относятся к структуре данных под названием “Куча” ( heap ). Если есть крупные объекты (или) ссылки на подобные, то с большой долей вероятности возникнет ошибка OutofMemory . Она может появиться по нескольким причинам:

  • Использование 32-битной архитектуры Python (максимальный объем выделенной памяти невысокий, между 2 и 4 ГБ);
  • Загрузка файла большого размера;
  • Запуск модели машинного обучения/глубокого обучения и много другое;

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

Но поскольку Python использует архитектуру управления памятью из языка C (функция malloc() ), не факт, что все процессы восстановятся — в некоторых случаях MemoryError приведет к остановке. Следовательно, обрабатывать такие ошибки не рекомендуется, и это не считается хорошей практикой.

Ошибка рекурсии (RecursionError)

Эта ошибка связана со стеком и происходит при вызове функций. Как и предполагает название, ошибка рекурсии возникает, когда внутри друг друга исполняется много методов (один из которых — с бесконечной рекурсией), но это ограничено размером стека.

Все локальные переменные и методы размещаются в стеке. Для каждого вызова метода создается стековый кадр (фрейм), внутрь которого помещаются данные переменной или результат вызова метода. Когда исполнение метода завершается, его элемент удаляется.

Чтобы воспроизвести эту ошибку, определим функцию recursion , которая будет рекурсивной — вызывать сама себя в бесконечном цикле. В результате появится ошибка StackOverflow или ошибка рекурсии, потому что стековый кадр будет заполняться данными метода из каждого вызова, но они не будут освобождаться.

Ошибка отступа (IndentationError)

Эта ошибка похожа по духу на синтаксическую и является ее подвидом. Тем не менее она возникает только в случае проблем с отступами.

Исключения

Даже если синтаксис в инструкции или само выражение верны, они все равно могут вызывать ошибки при исполнении. Исключения Python — это ошибки, обнаруживаемые при исполнении, но не являющиеся критическими. Скоро вы узнаете, как справляться с ними в программах Python. Объект исключения создается при вызове исключения Python. Если скрипт не обрабатывает исключение явно, программа будет остановлена принудительно.

Программы обычно не обрабатывают исключения, что приводит к подобным сообщениям об ошибке:

Ошибка типа (TypeError)

Ошибка деления на ноль (ZeroDivisionError)

Есть разные типы исключений в Python и их тип выводится в сообщении: вверху примеры TypeError и ZeroDivisionError . Обе строки в сообщениях об ошибке представляют собой имена встроенных исключений Python.

Оставшаяся часть строки с ошибкой предлагает подробности о причине ошибки на основе ее типа.

Теперь рассмотрим встроенные исключения Python.

Встроенные исключения

Прежде чем переходить к разбору встроенных исключений быстро вспомним 4 основных компонента обработки исключения, как показано на этой схеме.

  • Try : он запускает блок кода, в котором ожидается ошибка.
  • Except : здесь определяется тип исключения, который ожидается в блоке try (встроенный или созданный).
  • Else : если исключений нет, тогда исполняется этот блок (его можно воспринимать как средство для запуска кода в том случае, если ожидается, что часть кода приведет к исключению).
  • Finally : вне зависимости от того, будет ли исключение или нет, этот блок кода исполняется всегда.

В следующем разделе руководства больше узнаете об общих типах исключений и научитесь обрабатывать их с помощью инструмента обработки исключения.

Ошибка прерывания с клавиатуры (KeyboardInterrupt)

Исключение KeyboardInterrupt вызывается при попытке остановить программу с помощью сочетания Ctrl + C или Ctrl + Z в командной строке или ядре в Jupyter Notebook. Иногда это происходит неумышленно и подобная обработка поможет избежать подобных ситуаций.

В примере ниже если запустить ячейку и прервать ядро, программа вызовет исключение KeyboardInterrupt . Теперь обработаем исключение KeyboardInterrupt .

Стандартные ошибки (StandardError)

Рассмотрим некоторые базовые ошибки в программировании.

Арифметические ошибки (ArithmeticError)

  • Ошибка деления на ноль (Zero Division);
  • Ошибка переполнения (OverFlow);
  • Ошибка плавающей точки (Floating Point);

Все перечисленные выше исключения относятся к классу Arithmetic и вызываются при ошибках в арифметических операциях.

Деление на ноль (ZeroDivisionError)

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

Переполнение (OverflowError)

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

Ошибка утверждения (AssertionError)

Когда инструкция утверждения не верна, вызывается ошибка утверждения.

Рассмотрим пример. Предположим, есть две переменные: a и b . Их нужно сравнить. Чтобы проверить, равны ли они, необходимо использовать ключевое слово assert , что приведет к вызову исключения Assertion в том случае, если выражение будет ложным.

Ошибка атрибута (AttributeError)

При попытке сослаться на несуществующий атрибут программа вернет ошибку атрибута. В следующем примере можно увидеть, что у объекта класса Attributes нет атрибута с именем attribute .

Ошибка импорта (ModuleNotFoundError)

Ошибка импорта вызывается при попытке импортировать несуществующий (или неспособный загрузиться) модуль в стандартном пути или даже при допущенной ошибке в имени.

Ошибка поиска (LookupError)

LockupError выступает базовым классом для исключений, которые происходят, когда key или index используются для связывания или последовательность списка/словаря неверна или не существует.

Здесь есть два вида исключений:

Ошибка ключа

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

Ошибка индекса

Если пытаться получить доступ к индексу (последовательности) списка, которого не существует в этом списке или находится вне его диапазона, будет вызвана ошибка индекса (IndexError: list index out of range python).

Ошибка памяти (MemoryError)

Как уже упоминалось, ошибка памяти вызывается, когда операции не хватает памяти для выполнения.

Ошибка имени (NameError)

Ошибка имени возникает, когда локальное или глобальное имя не находится.

В следующем примере переменная ans не определена. Результатом будет ошибка NameError .

Ошибка выполнения (Runtime Error)

Ошибка «NotImplementedError»
Ошибка выполнения служит базовым классом для ошибки NotImplemented . Абстрактные методы определенного пользователем класса вызывают это исключение, когда производные методы перезаписывают оригинальный.

Ошибка типа (TypeError)

Ошибка типа вызывается при попытке объединить два несовместимых операнда или объекта.

В примере ниже целое число пытаются добавить к строке, что приводит к ошибке типа.

Ошибка значения (ValueError)

Ошибка значения вызывается, когда встроенная операция или функция получают аргумент с корректным типом, но недопустимым значением.

В этом примере встроенная операция float получат аргумент, представляющий собой последовательность символов (значение), что является недопустимым значением для типа: число с плавающей точкой.

Пользовательские исключения в Python

В Python есть много встроенных исключений для использования в программе. Но иногда нужно создавать собственные со своими сообщениями для конкретных целей.

Это можно сделать, создав новый класс, который будет наследовать из класса Exception в Python.

В предыдущем примере если ввести что-либо меньше 1, будет вызвано исключение. Многие стандартные исключения имеют собственные исключения, которые вызываются при возникновении проблем в работе их функций.

Недостатки обработки исключений в Python

У использования исключений есть свои побочные эффекты, как, например, то, что программы с блоками try-except работают медленнее, а количество кода возрастает.

Дальше пример, где модуль Python timeit используется для проверки времени исполнения 2 разных инструкций. В stmt1 для обработки ZeroDivisionError используется try-except, а в stmt2 — if . Затем они выполняются 10000 раз с переменной a=0 . Суть в том, чтобы показать разницу во времени исполнения инструкций. Так, stmt1 с обработкой исключений занимает больше времени чем stmt2 , который просто проверяет значение и не делает ничего, если условие не выполнено.

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

Выводы!

Как вы могли увидеть, обработка исключений помогает прервать типичный поток программы с помощью специального механизма, который делает код более отказоустойчивым.

Обработка исключений — один из основных факторов, который делает код готовым к развертыванию. Это простая концепция, построенная всего на 4 блоках: try выискивает исключения, а except их обрабатывает.

Очень важно поупражняться в их использовании, чтобы сделать свой код более отказоустойчивым.

Источники:

https://python-scripts. com/code-analysis

https://pythonru. com/osnovy/znachenija-iskljuchenij-i-oshibok-v-python

Понравилась статья? Поделиться с друзьями:
Добавить комментарий

;-) :| :x :twisted: :smile: :shock: :sad: :roll: :razz: :oops: :o :mrgreen: :lol: :idea: :grin: :evil: :cry: :cool: :arrow: :???: :?: :!: