Что такое исключения python
Перейти к содержимому

Что такое исключения python

  • автор:

Исключения и их обработка в Python

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

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

>>> 1a = 10 File "", line 1 1a = 10 ^ SyntaxError: invalid decimal literal

В терминологии языка Python здесь возникло исключение, принадлежащее классу SyntaxError . Согласно документации Python синтаксические ошибки все-таки принято относить к ошибкам, а все остальные – к исключениям. В некоторых языках программирования не используется слово «исключение», а ошибки делят на синтаксические и семантические. Нарушение семантики обычно означает, что, хотя выражения написаны верно с точки зрения синтаксиса языка, программа не работает так, как от нее ожидалось. Для сравнения. Вы можете грамотным русским языком сказать несколько предложений, но по смыслу это будет белиберда, или вас поймут не так, как вы думали.

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

Если вы попытаетесь обратиться к переменной, которой не было присвоено значение, что в случае Python означает, что переменная вообще не была объявлена, она не существует, то возникнет исключение NameError .

>>> a = 0 >>> print(a + b) Traceback (most recent call last): File "", line 1, in NameError: name 'b' is not defined

Последнюю строку сообщения можно перевести как «Ошибка имени: имя ‘b’ не определено».

Если исключение возникает при выполнении кода из файла, то вместо line 1 будет указана строка, в которой оно возникло, например, line 24 . Вместо будет указано имя файла, например, test.py . В данном же случае stdin обозначает стандартный поток ввода. По-умолчанию это поток ввода с клавиатуры. Строка 1 – потому что в интерактивном режиме каждое выражение интерпретируется отдельно, как обособленная программка. Если написать выражение, состоящее из нескольких строк, то линия возникновения ошибки может быть другой:

>>> a = 0 >>> if a == 0: . print(a) . print(a + b) . 0 Traceback (most recent call last): File "", line 3, in NameError: name 'b' is not defined

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

>>> int("Hi") Traceback (most recent call last): File "", line 1, in ValueError: invalid literal for int() with base 10: 'Hi' >>> >>> 8 + "3" Traceback (most recent call last): File "", line 1, in TypeError: unsupported operand type(s) for +: 'int' and 'str'

В примере строку «Hi» нельзя преобразовать к целому числу. Возникает исключение ValueError , потому что функция int() не может преобразовать такое значение.

Число 8 и строка «3» принадлежат разным типам, операнд сложения между которыми не поддерживается. При попытке их сложить возникает исключение TypeError .

Деление на ноль вызывает исключение ZeroDivisionError :

>>> 1/0 Traceback (most recent call last): File "", line 1, in ZeroDivisionError: division by zero

Обработка исключений. Оператор try-except

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

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

В Питоне такой перехват выполняет оператор try-except. «Try» переводится как «попытаться», «except» – как исключение. Словами описать его работу можно так: «Попытаться сделать то-то и то-то, если при этом возникло исключение, то сделать вот это и это.» Его конструкция похожа на условный оператор с веткой else . Рассмотрим пример:

n = input("Введите целое число: ") try: n = int(n) print("Удачно") except: print("Что-то пошло не так")

Исключительная ситуация может возникнуть в третьей строчке кода, когда значение переменной n преобразуется к целому числу. Если это невозможно, то дальнейшее выполнение выражений в теле try прекращается. В данном случае выражение print(«Удачно») выполнено не будет. При этом поток выполнения программы перейдет на ветку except и выполнит ее тело.

Если в теле try исключения не возникает, то тело ветки except не выполняется.

Вот пример вывода программы, когда пользователь вводит целое число:

Введите целое число: 100 Удачно

А здесь – когда вводит не то, что ожидалось:

Введите целое число: AA Что-то пошло не так

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

try: n = input('Введите целое число: ') n = int(n) print("Все нормально. Вы ввели число", n) except ValueError: print("Вы ввели не целое число")

Теперь если сработает тело except мы точно знаем, из-за чего возникла ошибка. Но если в теле try возникнет еще какое-нибудь исключение, то оно не будет обработано. Для него надо написать отдельную ветку except . Рассмотрим программу:

try: a = float(input("Введите делимое: ")) b = float(input("Введите делитель: ")) c = a / b print("Частное: %.2f" % c) except ValueError: print("Нельзя вводить строки") except ZeroDivisionError: print("Нельзя делить на ноль")

При ее выполнении исключения могут возникнуть в трех строчках кода: где происходит преобразование введенных значений к вещественным числам и в месте, где происходит деление. В первом случае может возникнуть ValueError , во втором – ZeroDivisionError . Каждый тип исключения обрабатывается своей веткой except .

Несколько исключений можно сгруппировать в одну ветку и обработать совместно:

try: a = float(input("Введите делимое: ")) b = float(input("Введите делитель: ")) c = a / b print("Частное: %.2f" % c) except (ValueError, ZeroDivisionError): print("Нельзя вводить строки") print("или делить на ноль")

У оператора обработки исключений, кроме except , могут быть еще ветки finally и else (не обязательно обе сразу). Тело finally выполняется всегда, независимо от того, выполнялись ли блоки except в ответ на возникшие исключения или нет. Тело else сработает, если исключений в try не было, то есть не было переходов на блоки except .

try: n = input('Введите целое число: ') n = int(n) except ValueError: print("Неверный ввод") else: # когда в блоке try не возникло исключения print("Все нормально. Вы ввели число", n) finally: # выполняется в любом случае print("Конец программы")

Примечание. В данном коде используются комментарии. В языке Python перед ними ставится знак решетки # . Комментарии в программном коде пишутся исключительно для человека и игнорируются интерпретатором или компилятором.

Посмотрите, как выполняется программа в случае возникновения исключения и без этого:

Введите целое число: 4.3 Неверный ввод Конец программы
Введите целое число: 4 Все нормально. Вы ввели число 4 Конец программы

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

Также исключение может возникнуть в блоке except , else или finally , и тогда им нужен собственный обработчик. Модифицируем немного предыдущую программу и специально сгенерируем исключение в теле except :

try: n = input('Введите целое число: ') n = int(n) except ValueError: print("Неверный ввод") 3 / 0 except ZeroDivisionError: print("Деление на ноль") else: print("Все нормально. Вы ввели число", n) finally: print("Конец программы")

По началу может показаться, что все нормально. Исключение, генерируемое выражением 3 / 0 будет обработано веткой except ZeroDivisionError . Однако это не так. Эта ветка обрабатывает только исключения, возникающие в блоке try , к которому она сама относится. Вот вывод программы, если ввести не целое число:

Введите целое число: а Неверный ввод Конец программы Traceback (most recent call last): File "test.py", line 15, in n = int(n) ValueError: invalid literal for int() with base 10: 'а' During handling of the above exception, another exception occurred: Traceback (most recent call last): File "test.py", line 18, in 3 / 0 ZeroDivisionError: division by zero

Мало того, что не было обработано деление на ноль, поскольку тело except ValueError неудачно завершилось, само исключение ValueError посчиталось необработанным. Решение проблемы может быть, например, таким:

except ValueError: print("Неверный ввод") try: 3 / 0 except ZeroDivisionError: print("Деление на ноль")

Здесь в тело except вложен свой внутренний обработчик исключений.

Практическая работа

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

Примеры выполнения программы:

Первое значение: 4 Второе значение: 5 Результат: 9.0
Первое значение: a Второе значение: 9 Результат: a9

Примеры решения и дополнительные уроки в pdf-версии курса

X Скрыть Наверх

Python. Введение в программирование

Исключения в python. Конструкция try — except для обработки исключений

Python 3 логотип

Исключения (exceptions) — ещё один тип данных в python. Исключения необходимы для того, чтобы сообщать программисту об ошибках.

Самый простейший пример исключения — деление на ноль:

Разберём это сообщение подробнее: интерпретатор нам сообщает о том, что он поймал исключение и напечатал информацию (Traceback (most recent call last)).

Далее имя файла (File «»). Имя пустое, потому что мы находимся в интерактивном режиме, строка в файле (line 1);

Выражение, в котором произошла ошибка (100 / 0).

Название исключения (ZeroDivisionError) и краткое описание исключения (division by zero).

Разумеется, возможны и другие исключения:

В этих двух примерах генерируются исключения TypeError и ValueError соответственно. Подсказки дают нам полную информацию о том, где порождено исключение, и с чем оно связано.

Рассмотрим иерархию встроенных в python исключений, хотя иногда вам могут встретиться и другие, так как программисты могут создавать собственные исключения. Данный список актуален для python 3.3, в более ранних версиях есть незначительные изменения.

  • BaseException — базовое исключение, от которого берут начало все остальные.
    • SystemExit — исключение, порождаемое функцией sys.exit при выходе из программы.
    • KeyboardInterrupt — порождается при прерывании программы пользователем (обычно сочетанием клавиш Ctrl+C).
    • GeneratorExit — порождается при вызове метода close объекта generator.
    • Exception — а вот тут уже заканчиваются полностью системные исключения (которые лучше не трогать) и начинаются обыкновенные, с которыми можно работать.
      • StopIteration — порождается встроенной функцией next, если в итераторе больше нет элементов.
      • ArithmeticError — арифметическая ошибка.
        • FloatingPointError — порождается при неудачном выполнении операции с плавающей запятой. На практике встречается нечасто.
        • OverflowError — возникает, когда результат арифметической операции слишком велик для представления. Не появляется при обычной работе с целыми числами (так как python поддерживает длинные числа), но может возникать в некоторых других случаях.
        • ZeroDivisionError — деление на ноль.
        • IndexError — индекс не входит в диапазон элементов.
        • KeyError — несуществующий ключ (в словаре, множестве или другом объекте).
        • UnboundLocalError — сделана ссылка на локальную переменную в функции, но переменная не определена ранее.
        • BlockingIOError
        • ChildProcessError — неудача при операции с дочерним процессом.
        • ConnectionError — базовый класс для исключений, связанных с подключениями.
          • BrokenPipeError
          • ConnectionAbortedError
          • ConnectionRefusedError
          • ConnectionResetError
          • IndentationError — неправильные отступы.
            • TabError — смешивание в отступах табуляции и пробелов.
            • UnicodeEncodeError — исключение, связанное с кодированием unicode.
            • UnicodeDecodeError — исключение, связанное с декодированием unicode.
            • UnicodeTranslateError — исключение, связанное с переводом unicode.

            Теперь, зная, когда и при каких обстоятельствах могут возникнуть исключения, мы можем их обрабатывать. Для обработки исключений используется конструкция try — except.

            Первый пример применения этой конструкции:

              
            
              
            

            Ещё две инструкции, относящиеся к нашей проблеме, это finally и else. Finally выполняет блок инструкций в любом случае, было ли исключение, или нет (применима, когда нужно непременно что-то сделать, к примеру, закрыть файл). Инструкция else выполняется в том случае, если исключения не было.

            Для вставки кода на Python в комментарий заключайте его в теги

            Мир Python: исключения — Python для продвинутых

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

            Исключительные ситуации или исключения (exceptions) – это ошибки, обнаруженные при исполнении. Например, к чему приведет попытка чтения несуществующего файла? Или если файл был случайно удален пока программа работала? Такие ситуации обрабатываются при помощи исключений.

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

            Простейший пример исключения - деление на ноль:

            >>> 100 / 0 Traceback (most recent call last): File "", line 1, in 100 / 0 ZeroDivisionError: division by zero 

            В данном случае интерпретатор сообщил нам об исключении ZeroDivisionError – делении на ноль.

            Traceback

            В большой программе исключения часто возникают внутри. Чтобы упростить программисту понимание ошибки и причины такого поведения Python предлагает Traceback или в сленге – трэйс. Каждое исключение содержит краткую информацию, но при этом полную, информацию о месте появления ошибки. По трэйсу найти и исправить ошибку становится проще.

            Рассмотрим такой пример:

            Traceback (most recent call last): File "/home/username/Develop/test/app.py", line 862, in _handle return route.call(**args) File "/home/username/Develop/test/app.py", line 1729, in wrapper rv = callback(*a, **ka) File "/home/username/Develop/test/__init__.py", line 76, in wrapper body = callback(*args, **kwargs) File "/home/username/Develop/test/my_app.py", line 16, in index raise Exception('test exception') 

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

            Рассмотрим какие ещё встречаются комментарии к исключениям:

            >>> 2 + '1' Traceback (most recent call last): File "", line 1, in 2 + '1' TypeError: unsupported operand type(s) for +: 'int' and 'str' 

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

            >>> int('qwerty') Traceback (most recent call last): File "", line 1, in int('qwerty') ValueError: invalid literal for int() with base 10: 'qwerty' 

            Приведение строчки к целому числу приводит к исключению ValueError.

            В трэйсе этих двух примеров можно прочесть, что в таком-то файле на такой-то строчке есть ошибки.

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

            Иерархия исключений

            Исключение, которое вы не увидите при выполнении кода – это BaseException – базовое исключение, от которого берут начало остальные.

            В иерархии исключений две основные группы:

            • Системные исключения и ошибки
            • Обыкновенные исключения

            Если обработку первых лучше не делать (если и делать, то надо четко понимать для чего), то обработку вторых целиком и полностью Python возлагает на плечи программиста.

            К системным можно смело отнести:

            • SystemExit – исключение, порождаемое функцией sys.exit при выходе из программы.
            • KeyboardInterrupt – возникает при прерывании программы пользователем (обычно сочетанием клавиш Ctrl+C).
            • GeneratorExit — возникает при вызове метода close объекта generator.

            Остальные исключения – это "обыкновенные". Спектр уже готовых исключений велик.

            Для Python2 иерархию исключений можно представить так:

            Python 2 Exception

            Список исключений покрывает большой объем ситуаций и ошибок программиста. Если предупреждения (warning) только просят обратить внимание, то ошибки уже могут остановить исполнение программы.

            В Python3 появились новые исключения и иерархия стала такова:

            Python3 Exception

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

            Использование исключений

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

            Начнем с обработки.

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

            Давайте рассмотрим случай с делением на 0.

            >>> a = 100 >>> b = 0 >>> c = a / b 

            Данный код приведет к исключению ZeroDivisionError. Чтобы этого не случилось, воспользуемся конструкцией try..except , например, так:

            >>> try: . a = 100 . b = 0 . c = a / b . except ZeroDivisionError as e: . print(e) . division by zero 

            Если исполнить этот код, то на консоль будет выведена строка "integer division or modulo by zero". Казалось бы, что толком ничего это нам не дало, ошибка все также есть. Однако в блок except можно поместить обработку.

            Например, мы условились, что значение переменной c в случае ошибки деления равно -1. Тогда модифицируем код:

            >>> try: . a = 100 . b = 0 . c = a / b . except ZeroDivisionError as e: . c = -1 >>> c -1 

            Перед тем как идти дальше, рассмотрим ещё одну возможность.

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

            Используя исключения, можно вот так решить эту задачу:

            try: filepath = 'test_file.txt' with open(filepath, 'r') as fio: result = fio.readlines() if not result: raise Exception("File is empty") except IOError as e: result = [] except Exception as e: result = [] print(e) 

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

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

            try: your_code except (IOError, Exception) as e: print(e) 

            Вызов исключений

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

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

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

            Чтобы бросить исключение необходимо воспользоваться raise

            raise IOError("текст исключения") 

            где IOError это класс исключения.

            Если при обработке исключения вы желаете пробросить его ещё выше, то следует написать такой код:

            try: your_code except Exception as e: raise 

            Собственные исключения

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

            В минимальном исполнении необходимо наследоваться от какого-нибудь класса в иерархии исключений. Например так:

            class MyException(Exception): pass 

            Тогда можно бросить своё исключение:

            raise MyException(Exception) 

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

            Как правило, исключения это очень маленькие классы. Они должны выполняться максимально быстро.

            Дополнение: Полная форма try..except

            Форма try. except не полная, полной же является try..except..else..finally .

            Применение полной конструкции может заметно упростить код, а также сделать его более безопасным.

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

            Иными словами, finally выполняет блок инструкций в любом случае, было ли исключение, или нет. А инструкция else выполняется в том случае, если исключения не было.

            В целом, использование полной формы таково:

            try: исполяем какой-то код except Exception as e: обработка исключения else: код, который будет исполнен в случае, когда не возникает исключения finally: код, который гарантированно будет исполнен последним (всегда исполняется) 

            Выводы

            В уроке рассмотрены вопросы связанные с исключениями:

            • Что такое исключение
            • Какие типы исключений присутствуют в языке
            • Как обрабатывать исключения
            • Как вызвать исключения
            • Как создавать собственные исключения

            Аватары экспертов Хекслета

            Остались вопросы? Задайте их в разделе «Обсуждение»

            Вам ответят команда поддержки Хекслета или другие студенты

            Об обучении на Хекслете

            • Статья «Как учиться и справляться с негативными мыслями»
            • Статья «Ловушки обучения»
            • Статья «Сложные простые задачи по программированию»
            • Вебинар « Как самостоятельно учиться »

            Открыть доступ

            Курсы программирования для новичков и опытных разработчиков. Начните обучение бесплатно

            • 130 курсов, 2000+ часов теории
            • 1000 практических заданий в браузере
            • 360 000 студентов

            Наши выпускники работают в компаниях:

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

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

            • Что такое обработка исключений?
            • Разница между оператором if и обработкой исключений.
            • Использование разделов else и finally блока try-except для организации правильного обращения с ошибками.
            • Определение пользовательских исключений.
            • Рекомендации по обработке исключений.

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

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

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

            Различия между оператором if и обработкой исключений

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

            Оператор if — это базовый строительный элемент структурного программирования. Этот оператор проверяет условие и выполняет различные блоки кода, основываясь на том, истинно проверяемое условие или ложно. Вот пример:

            temperature = int(input("Please enter temperature in Fahrenheit: ")) if temperature > 100: print("Hot weather alert! Temperature exceeded 100°F.") elif temperature >= 70: print("Warm day ahead, enjoy sunny skies.") else: print("Bundle up for chilly temperatures.")

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

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

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

            # Определение функции, которая пытается поделить число на ноль def divide(x, y): result = x / y return result # Вызов функции divide с передачей ей x=5 и y=0 result = divide(5, 0) print(f"Result of dividing by : ")
            Traceback (most recent call last): File "", line 8, in ZeroDivisionError: division by zero attempted

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

            Вышеописанное исключение можно обработать, обернув вызов функции divide в блок try-except :

            # Определение функции, которая пытается поделить число на ноль def divide(x, y): result = x / y return result # Вызов функции divide с передачей ей x=5 и y=0 try: result = divide(5, 0) print(f"Result of dividing by : ") except ZeroDivisionError: print("Cannot divide by zero.")
            Cannot divide by zero.

            Сделав это, мы аккуратно обработали исключение ZeroDivisionError , предотвратили аварийное завершение остального кода из-за необработанного исключения.

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

            Использование разделов else и finally блока try-except для организации правильного обращения с ошибками

            При работе с исключениями в Python рекомендуется включать в состав блоков try-except и раздел else , и раздел finally . Раздел else позволяет программисту настроить действия, производимые в том случае, если при выполнении кода, который защищают от проблем, не было вызвано исключений. А раздел finally позволяет обеспечить обязательное выполнение неких заключительных операций, вроде освобождения ресурсов, независимо от факта возникновения исключений (вот и вот — полезные материалы об этом).

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

            Использование разделов else и finally позволяет поступить именно так — обработать данные обычным образом в том случае, если исключений не возникло, либо обработать любые исключения, но, как бы ни развивались события, в итоге закрыть файл. Без этих разделов код страдал бы уязвимостями в виде утечки ресурсов или неполной обработки ошибок. В результате оказывается, что else и finally играют важнейшую роль в создании устойчивых к ошибкам и надёжных программ.

            try: # Открытие файла в режиме чтения file = open("file.txt", "r") print("Successful opened the file") except FileNotFoundError: # Обработка ошибки, возникающей в том случае, если файл не найден print("File Not Found Error: No such file or directory") exit() except PermissionError: # Обработка ошибок, связанных с разрешением на доступ к файлу print("Permission Denied Error: Access is denied") else: # Всё хорошо - сделать что-то с данными, прочитанными из файла content = file.read().decode('utf-8') processed_data = process_content(content) # Прибираемся после себя даже в том случае, если выше возникло исключение finally: file.close()

            В этом примере мы сначала пытаемся открыть файл file.txt для чтения (в подобной ситуации можно использовать выражение with , которое гарантирует правильное автоматическое закрытие объекта файла после завершения работы). Если в процессе выполнения операций файлового ввода/вывода возникают ошибки FileNotFoundError или PermissionError — выполняются соответствующие разделы except . Здесь, ради простоты, мы лишь выводим на экран сообщения об ошибках и выходим из программы в том случае, если файл не найден.

            В противном случае, если в блоке try исключений не возникло, мы продолжаем работу, обрабатывая содержимое файла в ветви else . И наконец — выполняется «уборка» — файл закрывается независимо от возникновения исключения. Это обеспечивает блок finally (подробности смотрите здесь).

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

            Определение пользовательских исключений

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

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

            Вот пример определения пользовательского исключения, названного InvalidEmailAddress :

            class InvalidEmailAddress(ValueError): def __init__(self, message): super().__init__(message) self.msgfmt = message

            Это исключение является наследником ValueError . Его конструктор принимает необязательный аргумент message (по умолчанию он устанавливается в значение invalid email address ).

            Вызвать это исключение можно в том случае, если в программе встретился адрес электронной почты, имеющий некорректный формат:

            def send_email(address): if isinstance(address, str) == False: raise InvalidEmailAddress("Invalid email address") # Отправка электронного письма

            Теперь, если функции send_email() будет передана строка, содержащая неправильно оформленный адрес, то, вместо сообщения стандартной ошибки TypeError , будет выдано настроенное заранее сообщение об ошибке, которое чётко указывает на возникшую проблему. Например, это может выглядеть так:

            >>> send_email(None) Traceback (most recent call last): File "", line 1, in File "/path/to/project/main.py", line 8, in send_email raise InvalidEmailAddress("Invalid email address") InvalidEmailAddress: Invalid email address

            Рекомендации по обработке исключений

            Вот несколько рекомендаций, относящихся к обработке ошибок в Python:

            1. Проектируйте код в расчёте на возможное возникновение ошибок. Заранее планируйте устройство кода с учётом возможных сбоев и проектируйте программы так, чтобы они могли бы достойно обрабатывать эти сбои. Это означает — предугадывать возможные пограничные случаи и реализовывать подходящие обработчики ошибок.
            2. Используйте содержательные сообщения об ошибках. Сделайте так, чтобы программа выводила бы, на экран, или в файл журнала, подробные сообщения об ошибках, которые помогут пользователям понять — что и почему пошло не так. Старайтесь не применять обобщённые сообщения об ошибках, наподобие Error occurred или Something bad happened . Вместо этого подумайте об удобстве пользователя и покажите сообщение, в котором будет дан совет по решению проблемы или будет приведена ссылка на документацию. Постарайтесь соблюсти баланс между выводом подробных сообщений и перегрузкой пользовательского интерфейса избыточными данными.
            3. Минимизируйте побочные эффекты. Постарайтесь свести к минимуму последствия сбойных операций, изолируя проблемные разделы кода посредством конструкции try-finally или try с использованием with . Сделайте так, чтобы после выполнения кода, было ли оно удачным или нет, обязательно выполнялись бы «очистительные» операции.
            4. Тщательно тестируйте код. Обеспечьте корректное поведение обработчиков ошибок в различных сценариях использования программы, подвергнув код всеобъемлющему тестированию.
            5. Регулярно выполняйте рефакторинг кода. Выполняйте рефакторинг фрагментов кода, подверженных ошибкам, чтобы улучшить их надёжность и производительность. Постарайтесь, чтобы ваша кодовая база была бы устроена по модульному принципу, чтобы её отдельные части слабо зависели бы друг от друга. Это позволяет независимым частям код самостоятельно эволюционировать, не оказывая негативного воздействия на другие его части.
            6. Логируйте важные события. Следите за интересными событиями своего приложения, записывая сведения о них в файл журнала или выводя в консоль. Это поможет вам выявлять проблемы на ранних стадиях их возникновения, не тратя время на длительный анализ большого количества неструктурированных логов.

            Итоги

            Написание кода обработки ошибок — это неотъемлемая часть индустрии разработки ПО, и, в частности — разработки на Python. Это позволяет разработчикам создавать более надёжные и стабильные программы. Следуя индустриальным стандартам и рекомендациям по обработке исключений, разработчик может сократить время, необходимое на отладку кода, способен обеспечить написание качественных программ и сделать так, чтобы пользователям было бы приятно работать с этими программами.

            О, а приходите к нам работать? �� ��

            Мы в wunderfund.io занимаемся высокочастотной алготорговлей с 2014 года. Высокочастотная торговля — это непрерывное соревнование лучших программистов и математиков всего мира. Присоединившись к нам, вы станете частью этой увлекательной схватки.

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

            Сейчас мы ищем плюсовиков, питонистов, дата-инженеров и мл-рисерчеров.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *