Найти ошибку в коде 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 в социальной сети ВК. Видео уроки и книги для вас!

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

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

Наш 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 исключения, важно понять, что есть тонкая грань между понятиями ошибки и исключения.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Исключения

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Ошибка ключа

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Выводы!

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

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

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

? Найдите и исправьте ошибки в коде на Python: отладка с IDLE

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

IDLE (Integrated Development and Learning Environment) – кроссплатформенная интегрированная среда разработки и обучения для Python, созданная Гвидо ван Россумом.

Используйте окно управления отладкой

Основным интерфейсом отладки в IDLE является специальное окно управления (Debug Control window). Открыть его можно, выбрав в меню интерактивного окна пункт Debug→Debugger.

Примечание: если отладка отсутствует в строке меню, убедитесь, что интерактивное окно находится в фокусе.

Всякий раз, когда окно отладки открыто, интерактивное окно отображает [DEBUG ON].

Обзор окна управления отладкой

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

Сохраните все, откройте окно отладки и нажмите клавишу F5 – выполнение не завершилось.

Окно отладки будет выглядеть следующим образом:

Обратите внимание, что панель в верхней части окна содержит сообщение:

Расшифруем: код for i in range(1, 4): еще не запущен, а ‘__main__’.module() сообщает, что в данный момент мы находимся в основном разделе программы, а не в определении функции.

Ниже панели стека находится панель Locals, в которой перечислены непонятные вещи: __annotations__, __builtins__, __doc__ и т. д. – это внутренние системные переменные, которые пока можно игнорировать. По мере выполнения программы переменные, объявленные в коде и отображаемые в этом окне, помогут в отслеживании их значений.

В левом верхнем углу окна расположены пять кнопок: Go, Step, Over, Out и Quit – они управляют перемещением отладчика по коду.

В следующих разделах вы узнаете, что делает каждая из этих кнопок.

Кнопка Step

Нажмите Step и окно отладки будет выглядеть следующим образом:

Обратите внимание на два отличия. Во-первых, сообщение на панели стека изменилось:

На этом этапе выполняется line 1 и отладчик останавливается перед выполнением line 2.

Здесь важно, что можно отслеживать растущие значения i и j по мере прохождения цикла for. Это полезная фича поиска источника ошибок в коде. Знание значения каждой переменной в каждой строке кода может помочь точно определить проблемную зону.

Точки останова и кнопка Go

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

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

Чтобы установить точку останова, щелкните правой кнопкой мыши (Ctrl для Mac) по строке кода, на которой хотите сделать паузу, и выберите пункт Set Breakpoint – IDLE выделит линию желтым. Чтобы удалить ее, выберите Clear Breakpoint.

Установите точку останова в строке с оператором print(). Окно редактора должно выглядеть так:

Сохраните и запустите. Как и раньше, панель стека указывает, что отладчик запущен и ожидает выполнения line 1. Нажмите кнопку Go и посмотрите, что произойдет:

Теперь на панели стека информация о выполнении line 3:

На панели Locals мы видим, что переменные i и j имеют значения 1 и 2 соответственно. Нажмем кнопку Go и попросим отладчик запускать код до точки останова или до конца программы. Снова нажмите Go – окно отладки теперь выглядит так:

На панели стека отображается то же сообщение, что и раньше – отладчик ожидает выполнения line 3. Однако значения переменных i и j теперь равны 2 и 4. Интерактивное окно также отображает выходные данные после первого запуска строки с помощью функции print() через цикл.

Нажмите кнопку в третий раз. Теперь i и j равны 3 и 6. Если нажать Go еще раз, программа завершит работу.

Over и Out

Кнопка Over работает, как сочетание Step и Go – она перешагивает через функцию или цикл. Другими словами, если вы собираетесь попасть в функцию с помощью отладчика, можно и не запускать код этой функции – кнопка Over приведет непосредственно к результату ее выполнения.

Аналогично если вы уже находитесь внутри функции или цикла – кнопка Out выполняет оставшийся код внутри тела функции или цикла, а затем останавливается.

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

Борьба с багами

Взглянем на « глючную » программу.

Вот неработающий код:

Введите этот код в редактор, сохраните и нажмите F5. Ожидаемый результат – _h_e_l_l_o_, но вместо этого выведется o_.

Если вы нашли, в чем проблема, не исправляйте ее. Наша цель – научиться использовать для этого IDLE.

Рассмотрим 4 этапа поиска бага:

Шаг 1: Предположение

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

Обратите внимание, что программа разделена на два раздела: определение функции add_underscores() и основной блок, определяющий переменную со значением «hello» и выводящий результат.

Посмотрим на основной раздел:

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

Первая строка создает переменную new_word со значением «_». Промах, проблема находится где-то в теле цикла for.

Шаг 2: точка останова

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

Запустим. Выполнение останавливается на строке с определением функции.

Нажмите кнопку Go, чтобы выполнить код до точки останова:

Код останавливается перед циклом for в функции add_underscores(). Обратите внимание, что на панели Locals отображаются две локальные переменные – word со значением «hello», и new_word со значением «_»,

Нажмите кнопку Step, чтобы войти в цикл for. Окно отладки изменится, и новая переменная i со значением 0 отобразится на панели Locals:

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

Нажмите кнопку Step еще раз и посмотрите на панель Locals – переменная new_word приняла значение «h_»:

Это неправильно т. к. сначала в new_word было значение «_», на второй итерации цикла for в ней должно быть «_h_». Если нажать Step еще несколько раз, то увидим, что в new_word попадает значение e_, затем l_ и так далее.

Шаг 3: Определение ошибки и исправление

Как мы уже выяснили – на каждой итерации цикла new_word перезаписывается следующим символом в строке «hello» и подчеркиванием. Поскольку внутри цикла есть только одна строка кода, проблема должна быть именно там:

Код указывает Python получить следующий символ word, прикрепить подчеркивание и назначить новую строку переменной new_word. Это именно то неверное поведение, которое мы наблюдали.

Чтобы все починить, нужно объединить word[i] + » _» с существующим значением new_word. Нажмите кнопку Quit в окне отладки, но не закрывайте его. Откройте окно редактора и измените строку внутри цикла for на следующую:

Примечание: Если бы вы закрыли отладчик, не нажав кнопку Quit, при повторном открытии окна отладки могла появиться ошибка:

You can only toggle the debugger when idle

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

Шаг 4: повторение шагов 1-3, пока ошибка не исчезнет

Сохраните изменения в программе и запустите ее снова. В окне отладки нажмите кнопку Go, чтобы выполнить код до точки останова. Понажимайте Step несколько раз и смотрите, что происходит с переменной new_word на каждой итерации – все работает, как положено. Иногда необходимо повторять этот процесс несколько раз, прежде чем исправится ошибка.

Альтернативные способы поиска ошибок

Использование отладчика может быть сложным и трудоемким, но это самый надежный способ найти ошибки в коде. Однако отладчики не всегда есть в наличии. В подобных ситуациях можно использовать print debugging для поиска ошибок в коде. PD задействует функцию print() для отображения в консоли текста, указывающего место выполнения программы и состояние переменных.

Например, вместо отладки предыдущего примера можно добавить следующую строку в конец цикла for:

Измененный код будет выглядеть следующим образом:

Вывод должен выглядеть так:

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

Один из способов улучшить наш цикл – перебирать символы в word:

Заключение

Теперь вы знаете все об отладке с помощью DLE. Вы можете использовать этот принцип с различными дебагерами.

Источники:

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

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

https://proglib. io/p/naydite-i-ispravte-oshibki-v-kode-na-python-otladka-s-idle-2020-11-10

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

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