Исключения

Введение

Примеры

  • 3

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

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

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

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

    Используйте 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") 
  • 1

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

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

    , 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)
    
     

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

  • 7

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

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

    В этом случае, просто используйте 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 
  • 0

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

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

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

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

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

    Например, 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 `` `
  • 2

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

    Исключением являются только обычные объекты 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 .

  • 3

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

    Создайте класс , унаследованный от 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)) 
  • 11

    Не лови все!

    В то время как это часто заманчивым , чтобы поймать каждый 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 - каждый из которых обычно следует обращаться иначе , чем обычные системы или логические ошибки. Это также означает, что нет четкого понимания того, что внутренний код может делать неправильно и как правильно восстанавливаться после этого состояния. Если вы ловите каждую ошибку, вы не будете знать, какая ошибка произошла или как ее исправить.

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

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

  • 7

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

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

    Первый заключается в создании кортежа типов исключений, которые вы хотите перехватить и обработать таким же образом. Этот пример заставит код игнорировать 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)
    
     
  • 2

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

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

    Представьте , что вы хотите, чтобы пользователь , чтобы ввести номер через 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 будет поднят при попытке получить значение из словаря для ключа , который не существует.

  • 5

    еще

    Код в блоке еще будет работать , только если никакие исключения не были подняты кодом в 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:
            ... 

Синтаксис

Параметры

Примечания