Документация по Python

Исключения

В: Документация по Python

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

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

 def even_the_odds(odds):
    if odds % 2 != 1:
        raise ValueError("Did not get an odd number")

    return odds + 1 

Ловить исключения

Используйте try...except: перехватывать исключения. Вы должны указать как можно более точное исключение:

 try:
    x = 5 / 0
except ZeroDivisionError as e:
    # `e` is the exception object
    print("Got a divide by zero! The exception was:", e)
    # handle exceptional case
    x = 0  
finally:
    print "The END"
    # it runs no matter what execute.

 

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

Например, ZeroDivisionError подкласс ArithmeticError :

 >>> ZeroDivisionError.__bases__
(<class 'ArithmeticError'>,)

 

Итак, следующий будет еще поймать ZeroDivisionError :

 try:
    5 / 0
except ArithmeticError:
    print("Got arithmetic error") 

Запуск кода очистки с помощью наконец

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

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

 resource = allocate_some_expensive_resource()
try:
    do_stuff(resource)
except SomeException as e:
    log_error(e)
    raise  # re-raise the error
finally:
    free_expensive_resource(resource)

 

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

Возрождение исключений

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

В этом случае, просто используйте raise заявление без каких - либо параметров.

 try:
    5 / 0
except ZeroDivisionError:
    print("Got an error")
    raise

 

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

 try:
    5 / 0
except ZeroDivisionError as e:
    raise ZeroDivisionError("Got an error", e)

 

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

В Python 3 вы можете сохранить первоначальный стек с помощью raise - from синтаксисом:

     raise ZeroDivisionError("Got an error") from e 

Цепные исключения с повышением от

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

Вы можете объединить исключения, чтобы показать, как происходит обработка исключений: `` `>>> try: 5/0 за исключением ZeroDivisionError как e: повысить ValueError (" Ошибка деления ") из e Traceback (последний вызов был последним): File"  ", строка 2, в  ZeroDivisionError: деление на ноль Вышеуказанное исключение было прямой причиной следующего исключения: обратная связь (последний вызов был последним): файл "  ", строка 4, в  ValueError: Разделение не удалось `` `

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

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

Например, IOError и OSError являются подклассами EnvironmentError . Код , который ловит IOError не поймать OSError . Тем не менее, код , который ловит EnvironmentError будет ловить как IOError s и OSError s.

Иерархия встроенных исключений:

`` `BaseException + - SystemExit + - KeyboardInterrupt + - GeneratorExit + - Exception + - StopIteration + - StandardError | + - BufferError | + - ArithmeticError | | + - FloatingPointError | | + - OverflowError | | + - ZeroDivisionError | + - AssertionError | + - AttributeError | + - EnvironmentError | | + - IOError | | + - OSError | | + - WindowsError (Windows) | | + - VMSError (VMS) | + - EOFError | + - ImportError | + - LookupError | | + - IndexError | | + - KeyError | + - MemoryError | + - NameError | | + - UnboundLocalError | + - ReferenceError | + - RuntimeError | | + - NotImplementedError | + - SyntaxError | | + - IndentationError | | + - TabError | + - SystemError | + - TypeError | + - ValueError | + - UnicodeError | + - UnicodeDecodeError | + - UnicodeEncodeError | + - UnicodeTranslateError + - Предупреждение + - Предупреждение об устаревании + - Предупреждение об ожидании + - Время выполнения + - Синтаксическое предупреждение + - Предупреждение пользователя + - FutureWarning + - ImportWarning + - UnicodeWarning + - BytesWarning `` `   `` `BaseException + - SystemExit + - KeyboardInterrupt + - GeneratorExit + - Exception + - StopIeror + - StopAsyncIteration + - ArithmeticError | + - FloatingPointError | + - OverflowError | + - ZeroDivisionError + - AssertionError + - AttributeError + - BufferError + - EOFError + - ImportError + - 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 + - Предупреждение + - Предупреждение об устаревании + - Предупреждение об ожидании + - Время выполнения + - Синтаксическое предупреждение + - Предупреждение пользователя + - FutureWarning + - ImportWarning + - UnicodeWarning + - BytesWarning + - ResourceWarning `` `

Исключения тоже объекты

Исключением являются только обычные объекты Python , которые наследуют от встроенного BaseException . Сценарий Python может использовать raise заявление , чтобы прервать выполнение, в результате чего Python для печати трассировки стеки из стека вызовов в этой точке и представление экземпляра исключения. Например:

 >>> def failing_function():
...     raise ValueError('Example error!')
>>> failing_function()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 2, in failing_function
ValueError: Example error! 

который говорит , что ValueError с сообщением 'Example error!' был поднят нашей failing_function() , который был выполнен в интерпретаторе.

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

 >>> try:
...     failing_function()
... except ValueError:
...     print('Handled the error')
Handled the error 

Вы можете разжиться объектов исключения, назначая их в except... часть кода обработки исключений:

 >>> try:
...     failing_function()
... except ValueError as e:
...     print('Caught exception', repr(e))
Caught exception ValueError('Example error!',) 

Полный список встроенных исключений Python вместе с их описаниями можно найти в документации по Python: https://docs.python.org/3.5/library/exceptions.html . А вот полный список организованы иерархически: https://codecamp.ru/documentation/python/1788/exceptions/5535/exception-hierarchy .

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

Создайте класс , унаследованный от Exception :

 class FooException(Exception):
    pass
try:
    raise FooException("insert description here")
except FooException:
    print("A FooException was raised.")

 

или другой тип исключения:

 class NegativeError(ValueError):
      pass

def foo(x):
    # function that only accepts positive values of x
    if x < 0:
        raise NegativeError("Cannot process negative numbers")
    ...  # rest of function body
try:
    result = foo(int(input("Enter a positive integer: ")))  # raw_input in Python 2.x
except NegativeError:
    print("You entered a negative number!")
else:
    print("The result was " + str(result)) 

Не лови все!

В то время как это часто заманчивым , чтобы поймать каждый Exception :

 try:
    very_difficult_function()
except Exception:
    # log / try to reconnect / exit gratiously
finally:
    print "The END"
    # it runs no matter what execute.

 

Или даже все (что включает в себя BaseException и всех его детей , включая Exception ):

 try:
    even_more_difficult_function()
except:
    pass  # do whatever needed

 

В большинстве случаев это плохая практика. Это может поймать больше , чем предполагалось, например, SystemExit , KeyboardInterrupt и MemoryError - каждый из которых обычно следует обращаться иначе , чем обычные системы или логические ошибки. Это также означает, что нет четкого понимания того, что внутренний код может делать неправильно и как правильно восстанавливаться после этого состояния. Если вы ловите каждую ошибку, вы не будете знать, какая ошибка произошла или как ее исправить.

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

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

Поймать несколько исключений

Есть несколько путей , чтобы поймать несколько исключений ,

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

 try:
    d = {}
    a = d[1]
    b = d.non_existing_field
except (KeyError, AttributeError) as e:
    print("A KeyError or an AttributeError exception has been caught.")

 

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

 try:
    d = {}
    a = d[1]
    b = d.non_existing_field
except KeyError as e:
    print("A KeyError has occurred. Exception message:", e)
except AttributeError as e:
    print("An AttributeError has occurred. Exception message:", e)

 

Практические примеры обработки исключений

Пользовательский ввод

Представьте , что вы хотите, чтобы пользователь , чтобы ввести номер через input . Вы хотите убедиться, что ввод является числом. Вы можете использовать try / за except для этого:

в то время как True: try: nb = int (input ('Введите число:')) break, кроме ValueError: print ("Это не число, попробуйте еще раз.")

Примечание: Python 2.x будет использовать raw_input вместо; функция input существует в Python 2.x , но имеет различную семантику. В приведенном выше примере, input также будет принимать такие выражения, как 2 + 2 , которая является числом.

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

Словари

Представьте , что вы итерация список последовательных целых чисел, как range(n) , и у вас есть список словарей d , который содержит информацию о том, что можно сделать , когда вы столкнетесь с некоторыми особыми целыми числами, скажем , пропустить d[i] последующие.

 d = [{7: 3}, {25: 9}, {38: 5}]

for i in range(len(d)):
    do_stuff(i)
    try:
       dic = d[i]
       i += dic[i]
    except KeyError:
       i += 1

 

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

еще

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

Например:

 try:
    data = {1: 'one', 2: 'two'}
    print(data[1])
except KeyError as e:
    print('key not found')
else:
    raise ValueError()
# Output: one
# Output: ValueError

 

Обратите внимание , что этот вид else: не может быть объединен с if запуске другого придаточного к elif . Если у вас есть следующее , if это необходимо , чтобы остаться с отступом ниже, else: :

 try:
    ...
except ...:
    ...
else:
    if ...:
        ...
    elif ...:
        ...
    else:
        ... 
Еще от кодкамп
Замечательно! Вы успешно подписались.
Добро пожаловать обратно! Вы успешно вошли
Вы успешно подписались на кодкамп.
Срок действия вашей ссылки истек.
Ура! Проверьте свою электронную почту на наличие волшебной ссылки для входа.
Успех! Ваша платежная информация обновлена.
Ваша платежная информация не была обновлена.