ОБРАБОТКА ИСКЛЮЧЕНИЙ PYTHON БЛОК TRY

В этом материале речь пойдет о блоках try/except
, finally
и raise
. Вместе с тем будет рассмотрено, как создавать собственные исключения в Python.

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

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

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

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

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

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

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

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

Get the name of the class that exception object belongs:

   e.__class__.__name__
  
  

and using print_exc() function will also print stack trace which is essential info for any error message.

   from traceback import print_exc

class CustomException(Exception): pass

try:
    raise CustomException("hi")
except Exception as e:
    print ('type is:', e.__class__.__name__)
    print_exc()
    # print("exception happened!")
  
  

You will get output like this:

   type is: CustomException
Traceback (most recent call last):
  File "exc.py", line 7, in <module>
    raise CustomException("hi")
CustomException: hi
  
  

And after print and analysis, the code can decide not to handle exception and just execute raise
:

   from traceback import print_exc

class CustomException(Exception): pass

def calculate():
    raise CustomException("hi")

try:
    calculate()
except CustomException as e:
    # here do some extra steps in case of CustomException
    print('custom logic doing cleanup and more')
    # then re raise same exception
    raise
  
  
   custom logic doing cleanup and more
  
  

And interpreter prints exception:

   Traceback (most recent call last):
  File "test.py", line 9, in <module>
    calculate()
  File "test.py", line 6, in calculate
    raise CustomException("hi")
__main__.CustomException: hi
  
  

After raise
original exception continues to propagate further up the call stack. ( Beware of possible pitfall
) If you raise new exception it caries new (shorter) stack trace.

   from traceback import print_exc

class CustomException(Exception):
    def __init__(self, ok):
        self.ok = ok

def calculate():
    raise CustomException(False)

try:
    calculate()
except CustomException as e:
    if not e.ok:
        # Always use `raise` to rethrow exception
        # following is usually mistake, but here we want to stress this point
        raise CustomException(e.ok)
    print("handling exception")
  
  
   Traceback (most recent call last):
  File "test.py", line 13, in <module>
    raise CustomException(e.message)
__main__.CustomException: hi    
  
  

Notice how traceback does not include calculate()
function from line 9
which is the origin of original exception e
.

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

Рассмотрим разные типы исключений в Python, которые появляются при срабатывании исключения в коде Python.

Ключевое слово raise в Python

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

    ZeroDivisionError
  
  
   Traceback (most recent call last):
  File "<pyshell#2>", line 1, in <module>
    raise ZeroDivisionError
ZeroDivisionError
  
  

Разберемся на примере операции деления:

   ab  # вводим 1 затем 0
 b
     ZeroDivisionError
  
  
   Traceback (most recent call last):
  File "<pyshell#2>", line 3, in <module>
    raise ZeroDivisionError
ZeroDivisionError
  
  

Здесь ввод пользователя в переменные a
и b
конвертируется в целые числа. Затем проверяется, равна ли b
нулю. Если да, то вызывается ZeroDivisionError
.

Что будет, если то же самое добавить в блоки try-except? Добавим следующее в код. Если запустить его, ввести 1 и 0, будет следующий вывод:

   ab

     b
         ZeroDivisionError

   "Деление на 0"
"Будет ли это напечатано?"
  
  
   1
0
Деление на 0
Будет ли это напечатано?
  
  

Рассмотрим еще несколько примеров, прежде чем двигаться дальше:

    KeyError
  
  
   Traceback (most recent call last):
  File “<pyshell#180>”, line 1, in <module>
    raise KeyError
KeyError
  
  


a. Raise без определенного исключения в Python

Можно использовать ключевое слово raise
и не указывая, какое исключение вызвать. Оно вызовет исключение, которое произошло. Поэтому его можно использовать только в блоке except
.

   
    

    
  
  
   Traceback (most recent call last):
  File “<pyshell#152>”, line 2, in <module>
    print(‘1’+1)
TypeError: must be str, not int
  
  


b. Raise с аргументом в Python

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

  ValueError

  
 Traceback (most recent call last):
  File "<pyshell#3>", line 1, in <module>
    raise ValueError("Несоответствующее значение")
ValueError: Несоответствующее значение

  

Общая обработка ошибок

   
   
  


    
   
 .() 



    
   
 ( % ) 

  

Однако изначально было:

   
   
 .() 

    
   
 : 

    
   
 ( % () ) 

  

Кто-то заметил, что «кроме исключения» ловится больше, чем просто «кроме исключения как e».

Почему это так? В чем разница?
ЛевКимбро

На данный момент (версия <= 2.4) исключение не обязательно должно быть унаследовано от Exception. Таким образом, простое «кроме:» перехватывает все исключения, а не только системные. Строковые исключения — это один из примеров исключений, которые не наследуются от Exception. — МайкРовнер

Я считаю, что начиная с версии 2.7 исключения по-прежнему не обязательно наследуются от Exception или даже BaseException
. Однако, начиная с Python 3, исключения должны
подкласс BaseException
. — СлонДжим

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

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

  i  
    

  
   File "<ipython-input-6-628f419d2da8>", line 2
    print('Привет Мир!')
        ^
IndentationError: expected an indented block

  

Исключения

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

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


Тип ошибки (TypeError)

 a  
b  
a  b

  
 ---------------------------------------------------------------------------

TypeError                                 Traceback (most recent call last)

<ipython-input-7-86a706a0ffdf> in <module>
      1 a = 2
      2 b = 'PythonRu'
----> 3 a + b


TypeError: unsupported operand type(s) for +: 'int' and 'str'

  


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

   

  
 ---------------------------------------------------------------------------

ZeroDivisionError                         Traceback (most recent call last)

<ipython-input-43-e9e866a10e2a> in <module>
----> 1 10 / 0


ZeroDivisionError: division by zero

  

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

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

Теперь рассмотрим встроенные выражения Python.

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

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

рассмотрим причину.

 a  
b  
c  a b

  
 File "<ipython-input-8-3b3ffcedf995>", line 3
 c = a b
       ^
SyntaxError: invalid syntax

  

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

О чем писать.

  • Приведите пример IOError и интерпретацию кода IOError.
  • Приведите пример нескольких исключений. Обработка нескольких исключений в одной строке.

Поиск конкретных имен исключений

Стандартные исключения, которые могут быть подняты, подробно описаны по адресу:

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

Блоки попробовать/исключить

Если код может привести к исключению, его лучше включить в блок try
. рассмотрим природу.

я
я

«Деление на 0»

«Исключение было обработано»

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

Следом идёт блок except
. Если не определить тип исключения, то он будет перехватывать любые. Другими словами, это общий обработчик исключений.

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

Читайте также:  Ошибка 0x80240438 в Windows Store

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


a. Несколько except в Python

У одного блока try
может быть несколько блоков except
. Рассмотрим примеры с несколькими вариантами обработки.

a b 

 ab
    "Это не будет напечатано"    

 
 TypeError
    "Вы сложили значения несовместимых типов"    

 ZeroDivisionError
    "Деление на 0"    

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

В первом примере первая инструкция приводит к ZeroDivisionError
. Эта ошибка обрабатывается в блоке except
, но инструкции в try
после первой не исполняются. Так происходит из-за того, что после первого исключения дальнейшие инструкции просто пропускаются. И если подходящий или общий блоки except
не удается найти, исключение не обрабатывается. В таком случае оставшаяся часть программы не будет запущена. Но если обработать исключение, то код после блоков except
и finally
исполнится. Попробуем.

a b 

 ab

    "Вы не можете разделить на 0"    

    "Будет ли это напечатано?"    

   Вы не можете разделить на 0
Будет ли это напечатано?
  
  


b. Несколько исключений в одном except

Можно использовать один блок except
для обработки нескольких исключений. Для этого используются скобки. Без них интерпретатор вернет синтаксическую ошибку
.

   
    
    
 TypeErrorZeroDivisionError
    
  
  
   Неверный ввод
  
  


c. Общий except после всех блоков except

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

   
    
    
    
 NameError
    "sum не существует"
 ZeroDivisionError
    "Вы не можете разделить на 0"

    
  
  
   Что-то пошло не так...
  
  

Здесь первая инструкция блока пытается осуществить операцию конкатенации строки python
с числом. Это приводит к ошибке TypeError
. Как только интерпретатор сталкивается с этой проблемой, он проверяет соответствующий блок except
, который ее обработает.

Отдельную инструкцию нельзя разместить между блоками try
и except
.

   
    


    
  
  

Это приведет к синтаксической ошибке.

Но может быть только один общий или блок по умолчанию типа except
. Следующий код вызовет ошибку «default 'except:' must be last»
:

   
    

    

    

    

  
  

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

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

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

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

    
     recursion

recursion
  
  
   ---------------------------------------------------------------------------

RecursionError                            Traceback (most recent call last)

<ipython-input-3-c6e0f7eb0cde> in <module>
----> 1 recursion()


<ipython-input-2-5395140f7f05> in recursion()
      1 def recursion():
----> 2     return recursion()


... last 1 frames repeated, from the frame below ...


<ipython-input-2-5395140f7f05> in recursion()
      1 def recursion():
----> 2     return recursion()


RecursionError: maximum recursion depth exceeded
  
  

Assert в Python

Утверждение (assert) — это санитарная проверка для вашего циничного, параноидального «Я». Оно принимает инструкцию в качестве аргумента и вызывает исключение Python, если возвращается значение False
. В противном случае выполняет операцию No-operation (NOP).

   
#  код работает дальше
  
  

Если бы инструкция была False
?

   
  
  
   Traceback (most recent call last):
  File “<pyshell#157>”, line 1, in <module>
    assert(1==0)
AssertionError
  
  

Возьмем другой пример:

   
    
     
    
     
    

    
    

    

  
  
   1
2
assert False.
Хорошо
Traceback (most recent call last):
  File “<pyshell#157>”, line 5, in <module>
    assert 1+2==4
AssertionError
  
  

Утверждения можно использовать для проверки валидности ввода и вывода в функции.


a. Второй аргумент для assert

Можно предоставить второй аргумент, чтобы дать дополнительную информацию о проблеме.

    
  
  
   Traceback (most recent call last):
  File “<pyshell#173>”, line 1, in <module>
    assert False,”Это проблема”
AssertionError: Это проблема
  
  

Getting Useful Information from an Exception

So, I’ve got something like:

           
       
:    

  

You know- you can put a print d
in there, and that works. Но есть ли лучший и более интересный способ получить ту информацию, о которой знают люди?

Вы можете сделать что-то вроде:

   
   
 , , = 

    
   
 : 

    
   
 . += (,) 

    
   
  

  

Обратите внимание, что не все исключения являются подклассами Exception (хотя почти все это делают), поэтому некоторые исключения могут быть не перехвачены; кроме того, исключения не обязаны иметь .args
атрибут (хотя это произойдет, если исключение является подклассом Exception и не переопределяет __init__
без вызова его суперкласса), поэтому написанный код может дать сбой. Но на практике этого почти никогда не происходит (а если и происходит, то вам следует исправить несовместимое исключение!)

(Обратите внимание, что это также аргумент в пользу проверяемых исключений Java — теперь ясно, что исключение может быть выброшено — за исключением того, что RuntimeException
еще можно кинуть куда угодно. -jJ)

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

  
х = 1
   
результат = моя функция (х) 

вы не можете определить, выйдет ли моя функция из строя во время выполнения, просто проверив ее, так почему же так важно, произойдет ли она из-за сбоя во время выполнения или из-за возникновения исключения?

(Сбой – это плохо. Явно объявляя исключение, вы предупреждаете людей, что они могут захотеть его обработать. Java делает это неловко. В C вообще нет хорошего способа сделать это, потому что возвращаемые ошибки все еще внутри полосы для регулярных возвратов. В Python исключения транзитной передачи не помечены, но условия ошибки выделяются там, где они создаются, и обычно они не имитируют действительные возвраты. -jJ)

Аргумент Джоэла о том, что создание исключений — это всего лишь замаскированный переход, отчасти верен. Но то же самое относится и к циклам for, циклам while, функциям и методам! Как и другие конструкции, исключения можно приручить и заставить работать на вас, а не дико и опасно. Прыгать *никуда* нельзя, только в сильно стесненных местах.

Джоэл также пишет:

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

(Даже сейчас довольно высокий процент ошибок, обнаруженных в коде C CPython, — это утечки памяти, вызванные преждевременным завершением работы — именно то, о чем предупреждал Джоэл. Это не такая проблема с кодом Python, потому что язык предполагается, что он позаботится об исправлении для вас инвариантов типа бухгалтерского учета. -jJ)

Это лучший аргумент в пользу *осторожного* использования исключений, а не аргумент в пользу их избежания. Или, что еще лучше, это аргумент в пользу написания кода, который не имеет побочных эффектов и реализует транзакции с данными. Это хорошая идея независимо от того, используете ли вы исключения или нет. (В Python «транзакции» настолько малы, что обычно сложно прервать операцию внутри одной операции без написания кода на C. Вы *можете* сделать это, скажем, с помощью рекурсивных генераторов, но это сложно.)

  
защита myfunc (x = Нет):
   
 результат = ""
   
 если x равен Нет:
   
 result = "Аргумент не указан"
   
 Элиф х == 0:
   
 результат = "Ноль"
   
 элиф 0 < х <= 3:
   
 resutl = "x находится между 0 и 3"
   
 еще:
   
 result = "x больше 3"
   
 вернуть результат 

Нет смысла откладывать возврат значения, как это делает myfunc, просто ради того, чтобы иметь единственную точку выхода. «Иметь единственную точку выхода» — хорошая эвристика для многих функций, но для данной — бессмысленная приработка. (На самом деле, это увеличивает, а не уменьшает вероятность ошибки. Если вы посмотрите внимательно, в myfunc выше есть такая ошибка в предложении «0 < x <= 3».)

Читайте также:  Построить код хэмминга для комбинации 101010 показать процесс исправления и обнаружения ошибки

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

Наконец, позвольте мне возразить против одного из комментариев Джоэла:

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

Возможно, это справедливо и для C++. Я не знаю языка и не хотел бы гадать. Но это не относится к Python.

(Разница в том, что Python в первую очередь снижает вероятность ошибки и делает создание исключения чистым способом «вернуть значение ошибки». Это определенно более чистый способ передать значение ошибки, которое был сгенерирован чем-то, что вы назвали.)

Вот как Джоэл мог бы написать функцию, будучи программистом на языке C:

  
защита joels_function(args):
   
 ошибка_результат = 0
   
 хороший_результат = Нет
   
 процесс(аргументы)
   
 если error_condition():
   
 error_result = -1 # флаг ошибки
   
 elif Different_error_conditon():
   
 error_result = -2
   
 еще:
   
 more_processing()
   
 если else_error_conditon():
   
 error_result = -3
   
 do_more_work()
   
 Good_result = "Успех!"
   
 если error_result != 0:
   
 возврат (Ложь, error_result)
   
 еще:
   
 возврат (Правда, хороший_результат) 

, а затем вызовите его с помощью:

  
статус, сообщение = joels_function(args)
   
если статус == Ложь:
   
 распечатать сообщение
   
 # и потерпеть неудачу.
   
еще:
   
 распечатать сообщение
   
 # и теперь продолжаем. 

Вот как бы я написал это на Python:

  
защита my_function(args):
   
 процесс(аргументы)
   
 если error_condition():
   
 поднять SomeError("Произошла ошибка")
   
 elif Different_error_conditon():
   
 поднять SomeError("Произошла другая ошибка")
   
 more_processing()
   
 если else_error_conditon():
   
 поднять SomeError("Произошла еще одна ошибка")
   
 do_more_work()
   
 вернуть «Успех!» 

и вызовите его с помощью:

  
пытаться:
   
 распечатать my_function(args)
   
кроме SomeError как сообщение:
   
 распечатать сообщение
   
 # и потерпеть неудачу.
   
# и теперь смело продолжайте здесь. 

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

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

(Извините, но если бы вы действительно много программировали на C++, вы бы знали, что между этими двумя языками нет большой разницы, когда дело касается исключений, по крайней мере, если вы не программируете C++ на старом языке. в стиле C с разбросанными повсюду операторами new и delete. По сути, вы отвергаете аргумент Джоэла. Весь этот раздел немного слаб, возможно, было бы лучше просто заявить: «Не злоупотребляйте исключениями, поскольку это может привести к трудно обрабатываемым -проверь код спагетти» и покончим с этим :)
–олау)



См. Также: итальянский перевод на ManutenereLeEccezioni .
.

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

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

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

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

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

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

   BaseException
  SystemExit
  KeyboardInterrupt
  GeneratorExit
  Exception
       StopIteration
       StopAsyncIteration
       ArithmeticError
           FloatingPointError
           OverflowError
           ZeroDivisionError
       AssertionError
       AttributeError
       BufferError
       EOFError
       ImportError
           ModuleNotFoundError
       LookupError
           IndexError
           KeyError
       MemoryError
       NameError
           UnboundLocalError
       OSError
           BlockingIOError
           ChildProcessError
           ConnectionError
               BrokenPipeError
               ConnectionAbortedError
               ConnectionRefusedError
               ConnectionResetError
           FileExistsError
           FileNotFoundError
           InterruptedError
           IsADirectoryError
           NotADirectoryError
           PermissionError
           ProcessLookupError
           TimeoutError
       ReferenceError
       RuntimeError
           NotImplementedError
           RecursionError
       SyntaxError
           IndentationError
                TabError
       SystemError
       TypeError
       ValueError
           UnicodeError
                UnicodeDecodeError
                UnicodeEncodeError
                UnicodeTranslateError
       Warning
            DeprecationWarning
            PendingDeprecationWarning
            RuntimeWarning
            SyntaxWarning
            UserWarning
            FutureWarning
            ImportWarning
            UnicodeWarning
            BytesWarning
            ResourceWarning
  
  

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

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

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


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

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

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

   
    inp  
    'Нажмите Ctrl+C и прервите Kernel:'
 KeyboardInterrupt
    

    'Исключений не произошло'

  
  
   Исключение KeyboardInterrupt
  
  

See Also

On this wiki: WritingExceptionClasses
, TracebackModule
.

For general (non-Python specific) ideas about exceptions, consult ExceptionPatterns
.

General Error Catching

However, there are some situations where it’s best to catch all
errors.

For example, suppose you are writing an extension module to a web service. You want the error information to output the output web page, and the server to continue to run, if at all possible. But you have no idea what kind of errors you might have put in your code.

In situations like these, you may want to code something like this:

           
       
    


          
       
 .()    



          
       
 ( % )    

  

MoinMoin
software is a good example of where general error catching is good. If you write Moin
Moin extension macros, and trigger an error, Moin
Moin will give you a detailed report of your error and the chain of events leading up to it. Python software needs to be able to catch all
errors, and deliver them to the recipient of the web page.

Another case is when you want to do something when code fails:



()

heap

()




()

By using

raise :)
with no arguments, you will re-raise the last exception. A common place to use this would be to roll back a transaction, or undo operations. If it’s a matter of cleanup that should be run regardless of success or failure, then you would do:

           
       
 ()    


          
       
 ()    

  

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

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


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

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

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


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

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

     
    a    
    a
 ZeroDivisionError  
     
  
    "Успех, нет ошибок!"
  
  
   Исключение ZeroDivisionError.
  
  


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

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

 
 math
 mathexp
 OverflowError 
 
 
    "Успех, нет ошибок!"    

   Исключение OverFlow.
  
  


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

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

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

 
 a 
 b 
 a b
 AssertionError 
 
 
    "Успех, нет ошибок!"    


   Исключение AssertionError.
  
  


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

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

    obj
    a  
    a


    obj  Attributes
    objattribute
 AttributeError
    

  
  
   2
Исключение AttributeError.
  
  


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

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

    nibabel
  
  
   ---------------------------------------------------------------------------

ModuleNotFoundError                       Traceback (most recent call last)

<ipython-input-6-9e567e3ae964> in <module>
----> 1 import nibabel


ModuleNotFoundError: No module named 'nibabel'
  
  


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


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

последовательность списка

/словаря неверна или не существует.

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

Ошибка индекса (
);

Ошибка ключа (
);

:)
Ошибка ключа


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

.

 
 a 
 a 
 LookupError 
 
 
    "Успех, нет ошибок!"    



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

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


 a 
 a 
 LookupError 
                
    "Исключение IndexError, индекс списка вне диапазона."

"Успех, нет ошибок!"
  • Ошибка памяти (MemoryError) OutofMemoryError

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

    MemoryError

                                   

    Ошибка имени (NameError) BaseException
    SystemExit
    KeyboardInterrupt
    GeneratorExit
    Exception
    StopIteration
    StopAsyncIteration
    ArithmeticError
    FloatingPointError
    OverflowError
    ZeroDivisionError
    AssertionError
    AttributeError
    BufferError
    EOFError
    ImportError
    ModuleNotFoundError
    LookupError
    IndexError
    KeyError
    MemoryError
    NameError
    UnboundLocalError
    OSError
    BlockingIOError
    ChildProcessError
    ConnectionError
    BrokenPipeError
    ConnectionAbortedError
    ConnectionRefusedError
    ConnectionResetError
    FileExistsError
    FileNotFoundError
    InterruptedError
    IsADirectoryError
    NotADirectoryError
    PermissionError
    ProcessLookupError
    TimeoutError
    ReferenceError
    RuntimeError
    NotImplementedError
    RecursionError
    SyntaxError
    IndentationError
    TabError
    SystemError
    TypeError
    ValueError
    UnicodeError
    UnicodeDecodeError
    UnicodeEncodeError
    UnicodeTranslateError
    Warning
    DeprecationWarning
    PendingDeprecationWarning
    RuntimeWarning
    SyntaxWarning
    UserWarning
    FutureWarning
    ImportWarning
    UnicodeWarning
    BytesWarning
    ResourceWarning

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

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

    .

    
     ans
     NameError 
        "NameError: переменная 'ans' не определена"    
    
     
        "Успех, нет ошибок!"    
    
    
       NameError: переменная 'ans' не определена
      
      


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

    Ошибка «NotImplementedError»


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

        
        
         self
            BaseClass self__init__
         self
    	# функция ничего не делает
             NotImplementedErrorself__class____name__  
    
     BaseClass
        
         self
            # действительно что-то делает
            self__class____name__  ' что-то делает!'
    
    SubClassdo_something
    BaseClassdo_something
    
      
      
       SubClass что-то делает!
    
    
    
    ---------------------------------------------------------------------------
    
    NotImplementedError                       Traceback (most recent call last)
    
    <ipython-input-1-57792b6bc7e4> in <module>
         14
         15 SubClass().do_something()
    ---> 16 BaseClass().do_something()
    
    
    <ipython-input-1-57792b6bc7e4> in do_something(self)
          5     def do_something(self):
          6         # функция ничего не делает
    ----> 7         raise NotImplementedError(self.__class__.__name__ + '.do_something')
          8
          9 class SubClass(BaseClass):
    
    
    NotImplementedError: BaseClass.do_something
      
      


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

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

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

       
        a  
        b  
        c  a  b
     TypeError
        
    
        'Успех, нет ошибок!'
    
      
      
       Исключение TypeError
      
      


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

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

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

    
     
     ValueError
        'ValueError: не удалось преобразовать строку в float: \'PythonRu\''    
    
    
        'Успех, нет ошибок!'    
    
    
       ValueError: не удалось преобразовать строку в float: 'PythonRu'
      
      


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

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

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

        Exception   
         self data    
            selfdata  data
         self
             selfdata
    
    Total_Marks  "Введите общее количество баллов: "
    
        Num_of_Sections  "Введите количество разделов: "
        Num_of_Sections  
             UnAcceptedValueError"Количество секций не может быть меньше 1"
     UnAcceptedValueError  e
         edata
    
      
      
       Введите общее количество баллов: 10
    Введите количество разделов: 0
    Полученная ошибка: Количество секций не может быть меньше 1
      
      

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


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

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

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

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

        timeit
    setup
    stmt1  '''\
    try:
        b=10/a
    except ZeroDivisionError:
        pass'''
    
    stmt2  '''\
    if a!=0:
        b=10/a'''
    
    timeittimeitstmt1setupnumber
    timeittimeitstmt2setupnumber
    
      
      
       time= 0.003897680000136461
    time= 0.0002797570000439009
      
      

    Handling Exceptions

               
           
    (,) = (,)    
    
    
              
           
     = /    
    
              
           
     :    
    
              
           
        divide by zero    
        
    
      

    If you wanted to examine the exception from code, you could have:

                                                 
                                                            

    (,) = (,)

    = /

    heap OutofMemory

    • :

    • =

    • malloc() MemoryError

      OutofMemoryError

    Объявление собственных исключений Python

                      
                      

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

    . Потом его можно будет вызывать как любой другой тип исключения. BaseException
    SystemExit
    KeyboardInterrupt
    GeneratorExit
    Exception
    StopIteration
    StopAsyncIteration
    ArithmeticError
    FloatingPointError
    OverflowError
    ZeroDivisionError
    AssertionError
    AttributeError
    BufferError
    EOFError
    ImportError
    ModuleNotFoundError
    LookupError
    IndexError
    KeyError
    MemoryError
    NameError
    UnboundLocalError
    OSError
    BlockingIOError
    ChildProcessError
    ConnectionError
    BrokenPipeError
    ConnectionAbortedError
    ConnectionRefusedError
    ConnectionResetError
    FileExistsError
    FileNotFoundError
    InterruptedError
    IsADirectoryError
    NotADirectoryError
    PermissionError
    ProcessLookupError
    TimeoutError
    ReferenceError
    RuntimeError
    NotImplementedError
    RecursionError
    SyntaxError
    IndentationError
    TabError
    SystemError
    TypeError
    ValueError
    UnicodeError
    UnicodeDecodeError
    UnicodeEncodeError
    UnicodeTranslateError
    Warning
    DeprecationWarning
    PendingDeprecationWarning
    RuntimeWarning
    SyntaxWarning
    UserWarning
    FutureWarning
    ImportWarning
    UnicodeWarning
    BytesWarning
    ResourceWarning


    Вот и все, что касается обработки исключений в Python.

    Блок finally в Python :)
    После последнего блока
    можно добавить блок


    . Он исполняет инструкции при любых условиях.


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

    А что будет, если исключение перехватывается в except
    ?

       
        
     ZeroDivisionError
        
    
        "Ничего не происходит"
      
      
       Ничего не происходит
    
    Traceback (most recent call last):
      File "<pyshell#1>", line 2, in <module>
        print(1/0)
    ZeroDivisionError: division by zero
    
    During handling of the above exception, another exception occurred:
    
    Traceback (most recent call last):
      File "<pyshell#1>", line 4, in <module>
        print(2/0)
    ZeroDivisionError: division by zero
      
      

    Как видите, код в блоке finally
    исполняется в любом случае.

    Выводы!

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

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

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

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

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

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

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