Обработка исключений в python
Содержание:
Дополнение: Полная форма try..except
Форма try…except не полная, полной же является try..except..else..finaly.
Применение полной конструкции может заметно упростить код, а также сделать его более безопасным.
Представим, что в программе происходит чтение файла и необходимо убедиться, что объект файла был корректно закрыт и что не возникло никакого исключения. Этого можно достичь с применением блока finally.
Иными словами, finally выполняет блок инструкций в любом случае, было ли исключение, или нет. А инструкция else выполняется в том случае, если исключения не было.
В целом, использование полной формы таково:
try исполяем какой-то код except Exception as e обработка исключения else код, который будет исполнен в случае, когда не возникает исключения finally код, который гарантированно будет исполнен последним (всегда исполняется)
The try-finally Clause
You can use a finally: block along with a try: block. The finally block is a place to put any code that must execute, whether the try-block
raised an exception or not. The syntax of the try-finally statement is this −
try: You do your operations here; ...................... Due to any exception, this may be skipped. finally: This would always be executed. ......................
You cannot use else clause as well along with a finally clause.
Example
#!/usr/bin/python try: fh = open("testfile", "w") fh.write("This is my test file for exception handling!!") finally: print "Error: can\'t find file or read data"
If you do not have permission to open the file in writing mode, then this will produce the following result −
Error: can't find file or read data
Same example can be written more cleanly as follows −
#!/usr/bin/python try: fh = open("testfile", "w") try: fh.write("This is my test file for exception handling!!") finally: print "Going to close the file" fh.close() except IOError: print "Error: can\'t find file or read data"
When an exception is thrown in the try block, the execution immediately passes to the finally block. After all the statements in the finally block are executed, the exception is raised again and is handled in the except statements if present in the next higher layer of the try-except statement.
Raising an Exceptions
You can raise exceptions in several ways by using the raise statement. The general syntax for the raise statement is as follows.
Syntax
raise ]]
Here, Exception is the type of exception (for example, NameError) and argument is a value for the exception argument. The argument is optional; if not supplied, the exception argument is None.
The final argument, traceback, is also optional (and rarely used in practice), and if present, is the traceback object used for the exception.
Example
An exception can be a string, a class or an object. Most of the exceptions that the Python core raises are classes, with an argument that is an instance of the class. Defining new exceptions is quite easy and can be done as follows −
def functionName( level ): if level < 1: raise "Invalid level!", level # The code below to this would not be executed # if we raise the exception
Note: In order to catch an exception, an «except» clause must refer to the same exception thrown either class object or simple string. For example, to capture above exception, we must write the except clause as follows −
try: Business Logic here... except "Invalid level!": Exception handling here... else: Rest of the code here...
User-Defined Exceptions
Python also allows you to create your own exceptions by deriving classes from the standard built-in exceptions.
Here is an example related to RuntimeError. Here, a class is created that is subclassed from RuntimeError. This is useful when you need to display more specific information when an exception is caught.
In the try block, the user-defined exception is raised and caught in the except block. The variable e is used to create an instance of the class Networkerror.
class Networkerror(RuntimeError): def __init__(self, arg): self.args = arg
So once you defined above class, you can raise the exception as follows −
try: raise Networkerror("Bad hostname") except Networkerror,e: print e.args
Previous Page
Print Page
Next Page
Catching Exceptions in Python
The try-except block can handle exceptions. This prevents abrupt exits of the program on error. In the example below we purposely raise an exception.
123456 |
try: 1 / except ZeroDivisionError: print('Divided by zero')print('Should reach here') |
After the except block, the program continues. Without a try-except block, the last line wouldn’t be reached as the program would crash.
In the above example we catch the specific exception ZeroDivisionError. You can handle any exception like this:
123456 |
try: open("fantasy.txt")except: print('Something went wrong')print('Should reach here') |
You can write different logic for each type of exception that happens:
12345678910 |
try: except FileNotFoundError: except IsADirectoryError:except:print('Should reach here') |
Related course: Complete Python Programming Course & Exercises
Multiple except clauses
An examination of use-cases shows that this is not needed as often as
it would be with the statement form, and as its syntax is a point on
which consensus has not been reached, the entire feature is deferred.
Multiple ‘except’ keywords could be used, and they will all catch
exceptions raised in the original expression (only):
# Will catch any of the listed exceptions thrown by expr; # any exception thrown by a default expression will propagate. value = (expr except Exception1: default1 except Exception2: default2 # ... except ExceptionN: defaultN )
Currently, one of the following forms must be used:
# Will catch an Exception2 thrown by either expr or default1 value = ( (expr except Exception1: default1) except Exception2: default2 ) # Will catch an Exception2 thrown by default1 only value = (expr except Exception1: (default1 except Exception2: default2) )
Использование исключений
Мы рассмотрели что такое исключения, какие они бывают и как их анализировать. Но до сих пор явно не рассмотрели такую важную вещь, как их использование.
Начнем с обработки.
Обработка исключений
Давайте рассмотрим случай с делением на 0.
a = 100 b = c = a b
Данный код приведет к исключению ZeroDivisionError. Чтобы этого не случилось, воспользуемся конструкцией try..except, например так:
try a = 100 b = c = a b except ZeroDivisionError as e print(e)
Если исполнить этот код, то на консоль будет выведена строка «integer division or modulo by zero». Казалось бы, что толком ничего это нам не дало, ошибка все также есть. Однако в блок except можно поместить обработку.
Например, мы условились, что значение переменной c в случае ошибки деления равно -1. Тогда модифицируем код:
try a = 100 b = c = a b except ZeroDivisionError as e 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)
Легко заметить, мы создаем класс, а значит все, что мы знаем о классах справедливо и для исключений. Можно завести переменные и делать их обработку.
Как правило, исключения это очень маленькие классы. Они должны выполняться максимально быстро.
Standard Exceptions
Here is a list of Standard Exceptions available in Python. −
Sr.No. | Exception Name & Description |
---|---|
1 |
Exception Base class for all exceptions |
2 |
StopIteration Raised when the next() method of an iterator does not point to any object. |
3 |
SystemExit Raised by the sys.exit() function. |
4 |
StandardError Base class for all built-in exceptions except StopIteration and SystemExit. |
5 |
ArithmeticError Base class for all errors that occur for numeric calculation. |
6 |
OverflowError Raised when a calculation exceeds maximum limit for a numeric type. |
7 |
FloatingPointError Raised when a floating point calculation fails. |
8 |
ZeroDivisonError Raised when division or modulo by zero takes place for all numeric types. |
9 |
AssertionError Raised in case of failure of the Assert statement. |
10 |
AttributeError Raised in case of failure of attribute reference or assignment. |
11 |
EOFError Raised when there is no input from either the raw_input() or input() function and the end of file is reached. |
12 |
ImportError Raised when an import statement fails. |
13 |
KeyboardInterrupt Raised when the user interrupts program execution, usually by pressing Ctrl+c. |
14 |
LookupError Base class for all lookup errors. |
15 |
IndexError Raised when an index is not found in a sequence. |
16 |
KeyError Raised when the specified key is not found in the dictionary. |
17 |
NameError Raised when an identifier is not found in the local or global namespace. |
18 |
UnboundLocalError Raised when trying to access a local variable in a function or method but no value has been assigned to it. |
19 |
EnvironmentError Base class for all exceptions that occur outside the Python environment. |
20 |
IOError Raised when an input/ output operation fails, such as the print statement or the open() function when trying to open a file that does not exist. |
21 |
OSError Raised for operating system-related errors. |
22 |
SyntaxError Raised when there is an error in Python syntax. |
23 |
IndentationError Raised when indentation is not specified properly. |
24 |
SystemError Raised when the interpreter finds an internal problem, but when this error is encountered the Python interpreter does not exit. |
25 |
SystemExit Raised when Python interpreter is quit by using the sys.exit() function. If not handled in the code, causes the interpreter to exit. |
26 |
TypeError Raised when an operation or function is attempted that is invalid for the specified data type. |
27 |
ValueError Raised when the built-in function for a data type has the valid type of arguments, but the arguments have invalid values specified. |
28 |
RuntimeError Raised when a generated error does not fall into any category. |
29 |
NotImplementedError Raised when an abstract method that needs to be implemented in an inherited class is not actually implemented. |
try/except¶
Если вы повторяли примеры, которые использовались ранее, то наверняка
были ситуации, когда выскакивала ошибка. Скорее всего, это была ошибка
синтаксиса, когда не хватало, например, двоеточия.
Как правило, Python довольно понятно реагирует на подобные ошибки, и их
можно исправить.
Тем не менее, даже если код синтаксически написан правильно, могут
возникать ошибки. В Python эти ошибки называются исключения (exceptions).
Примеры исключений:
In 1]: 2 ----------------------------------------------------- ZeroDivisionError division by zero In 2]: 'test' + 2 ----------------------------------------------------- TypeError must be str, not int
В данном случае возникло два исключения: ZeroDivisionError и
TypeError.
Чаще всего можно предсказать, какого рода исключения возникнут во время
исполнения программы.
Например, если программа на вход ожидает два числа, а на выходе выдает
их сумму, а пользователь ввел вместо одного из чисел строку, появится
ошибка TypeError, как в примере выше.
Python позволяет работать с исключениями. Их можно перехватывать и
выполнять определенные действия в том случае, если возникло исключение.
Примечание
Когда в программе возникает исключение, она сразу завершает работу.
Для работы с исключениями используется конструкция :
In 3]: try ... 2 ... except ZeroDivisionError ... print("You can't divide by zero") ... You can't divide by zero
Конструкция try работает таким образом:
- сначала выполняются выражения, которые записаны в блоке try
- если при выполнения блока try не возникло никаких исключений, блок except пропускается,
и выполняется дальнейший код - если во время выполнения блока try в каком-то месте возникло исключение,
оставшаяся часть блока try пропускается- если в блоке except указано исключение, которое возникло, выполняется код в блоке except
- если исключение, которое возникло, не указано в блоке except,
выполнение программы прерывается и выдается ошибка
Обратите внимание, что строка в блоке try не выводится:
In 4]: try ... print("Let's divide some numbers") ... 2 ... print('Cool!') ... except ZeroDivisionError ... print("You can't divide by zero") ... Let's divide some numbers You can't divide by zero
В конструкции try/except может быть много except, если нужны разные
действия в зависимости от типа ошибки.
Например, скрипт divide.py делит два числа введенных пользователем:
# -*- coding: utf-8 -*- try a = input("Введите первое число: ") b = input("Введите второе число: ") print("Результат: ", int(a)int(b)) except ValueError print("Пожалуйста, вводите только числа") except ZeroDivisionError print("На ноль делить нельзя")
Примеры выполнения скрипта:
$ python divide.py Введите первое число: 3 Введите второе число: 1 Результат: 3 $ python divide.py Введите первое число: 5 Введите второе число: 0 На ноль делить нельзя $ python divide.py Введите первое число: qewr Введите второе число: 3 Пожалуйста, вводите только числа
В данном случае исключение ValueError возникает, когда пользователь
ввел строку вместо числа, во время перевода строки в число.
Исключение ZeroDivisionError возникает в случае, если второе число было
равным 0.
Если нет необходимости выводить различные сообщения на ошибки ValueError
и ZeroDivisionError, можно сделать так (файл divide_ver2.py):
# -*- coding: utf-8 -*- try a = input("Введите первое число: ") b = input("Введите второе число: ") print("Результат: ", int(a)int(b)) except (ValueError, ZeroDivisionError): print("Что-то пошло не так...")
Проверка:
$ python divide_ver2.py Введите первое число: wer Введите второе число: 4 Что-то пошло не так... $ python divide_ver2.py Введите первое число: 5 Введите второе число: 0 Что-то пошло не так...
Заключение
Трассировка содержит важную информацию, которая может помочь вам найти, что идет не так в вашем коде. Эти следы могут выглядеть немного пугающими, но как только вы разберетесь с ними, чтобы увидеть, что они пытаются вам показать, они могут быть очень полезными. Изучение нескольких трассировок построчно даст вам лучшее понимание информации, которую они содержат, и поможет вам извлечь из них максимальную пользу.
Получение вывода трассировки при запуске вашего кода — это отличная возможность улучшить ваш код.
Теперь, когда вы знаете, как читать трассировку, вы можете больше узнать о некоторых инструментах и методах диагностики проблем, о которых рассказывает ваш вывод трассировки. Встроенный модуль может использоваться для работы и проверки трассировок. Модуль трассировки может быть полезен, когда вам нужно получить больше от результатов трассировки. Также было бы полезно узнать больше о некоторых методах отладки кода Python.
Spread the love