Данный урок посвящен исключениям и работе с ними. Основное внимание уделено понятию исключения в языках программирования, обработке исключений в Python, их генерации и созданию пользовательских исключений.
Исключения в языках программирования
Исключениями (exceptions) в языках программирования называют проблемы, возникающие в ходе выполнения программы, которые допускают возможность дальнейшей ее работы в рамках основного алгоритма. Типичным примером исключения является деление на ноль, невозможность считать данные из файла (устройства), отсутствие доступной памяти, доступ к закрытой области памяти и т.п. Для обработки таких ситуаций в языках программирования, как правило, предусматривается специальный механизм, который называется обработка исключений (exception handling).
Исключения разделяют на синхронные и асинхронные. Синхронные исключения могут возникнуть только в определенных местах программы. Например, если у вас есть код, который открывает файл и считывает из него данные, то исключение типа “ошибка чтения данных” может произойти только в указанном куске кода. Асинхронные исключения могут возникнуть в любой момент работы программы, они, как правило, связаны с какими-либо аппаратными проблемами, либо приходом данных. В качестве примера можно привести сигнал отключения питания.
В языках программирования чаще всего предусматривается специальный механизм обработки исключений. Обработка может быть с возвратом, когда после обработки исключения выполнение программы продолжается с того места, где оно возникло. И обработка без возврата, в этом случае, при возникновении исключения, осуществляется переход в специальный, заранее подготовленный, блок кода.
Различают структурную и неструктурную обработку исключений. Неструктурная обработка предполагает регистрацию функции обработчика для каждого исключения, соответственно данная функция будет вызвана при возникновении конкретного исключения. Для структурной обработки язык программирования должен поддерживать специальные синтаксические конструкции, которые позволяют выделить код, который необходимо контролировать и код, который нужно выполнить при возникновении исключительной ситуации.
В Python выделяют два различных вида ошибок: синтаксические ошибки и исключения.
Синтаксические ошибки в Python
Синтаксические ошибки возникают в случае если программа написана с нарушениями требований Python к синтаксису. Определяются они в процессе парсинга программы. Ниже представлен пример с ошибочным написанием функции print.
>>> for i in range(10): prin("hello!") Traceback (most recent call last): File "<pyshell#2>", line 2, in <module> prin("hello!") NameError: name 'prin' is not defined
Исключения в Python
Второй вид ошибок – это исключения. Они возникают в случае если синтаксически программа корректна, но в процессе выполнения возникает ошибка (деление на ноль и т.п.). Более подробно про понятие исключения написано выше, в разделе “исключения в языках программирования”.
Пример исключения ZeroDivisionError, которое возникает при делении на 0.
>>> a = 10 >>> b = 0 >>> c = a / b Traceback (most recent call last): File "<pyshell#5>", line 1, in <module> c = a / b ZeroDivisionError: division by zero
В Python исключения являются определенным типом данных, через который пользователь (программист) получает информацию об ошибке. Если в коде программы исключение не обрабатывается, то приложение останавливается и в консоли печатается подробное описание произошедшей ошибки с указанием места в программе, где она произошла и тип этой ошибки.
Иерархия исключений в Python
Существует довольно большое количество встроенных типов исключений в языке 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
Как видно из приведенной выше схемы, все исключения являются подклассом исключения BaseException. Более подробно об иерархии исключений и их описании можете прочитать здесь.
Обработка исключений в Python
Обработка исключений нужна для того, чтобы приложение не завершалось аварийно каждый раз, когда возникает исключение. Для этого блок кода, в котором возможно появление исключительной ситуации необходимо поместить во внутрь синтаксической конструкции try…except.
print("start") try: val = int(input("input number: ")) tmp = 10 / val print(tmp) except Exception as e: print("Error! " + str(e)) print("stop")
В приведенной выше программе возможных два вида исключений – это ValueError, возникающее в случае, если на запрос программы “введите число”, вы введете строку, и ZeroDivisionError – если вы введете в качестве числа 0.
Вывод программы при вводе нулевого числа будет таким.
start input number: 0 Error! stop
Если бы инструкций try…except не было, то при выбросе любого из исключений программа аварийно завершится.
print("start") val = int(input(“input number: “)) tmp = 10 / val print(tmp) print("stop")
Если ввести 0 на запрос приведенной выше программы, произойдет ее остановка с распечаткой сообщения об исключении.
start
input number: 0
Traceback (most recent call last):
File “F:/work/programming/python/devpractice/tmp.py”, line 3, in <module>
tmp = 10 / val
ZeroDivisionError: division by zero
Обратите внимание, надпись stop уже не печатается в конце вывода программы.
Согласно документу по языку Python, описывающему ошибки и исключения, оператор try работает следующим образом:
- Вначале выполняется код, находящийся между операторами try и except.
- Если в ходе его выполнения исключения не произошло, то код в блоке except пропускается, а код в блоке try выполняется весь до конца.
- Если исключение происходит, то выполнение в рамках блока try прерывается и выполняется код в блоке except. При этом для оператора except можно указать, какие исключения можно обрабатывать в нем. При возникновении исключения, ищется именно тот блок except, который может обработать данное исключение.
- Если среди except блоков нет подходящего для обработки исключения, то оно передается наружу из блока try. В случае, если обработчик исключения так и не будет найден, то исключение будет необработанным (unhandled exception) и программа аварийно остановится.
Для указания набора исключений, который должен обрабатывать данный блок except их необходимо перечислить в скобках (круглых) через запятую после оператора except.
Если бы мы в нашей программе хотели обрабатывать только ValueError и ZeroDivisionError, то программа выглядела бы так.
print("start") try: val = int(input("input number: ")) tmp = 10 / val print(tmp) except(ValueError, ZeroDivisionError): print("Error!") print("stop")
Или так, если хотим обрабатывать ValueError, ZeroDivisionError по отдельность, и, при этом, сохранить работоспособность при возникновении исключений отличных от вышеперечисленных.
print("start") try: val = int(input("input number: ")) tmp = 10 / val print(tmp) except ValueError: print("ValueError!") except ZeroDivisionError: print("ZeroDivisionError!") except: print("Error!") print("stop")
Существует возможность передать подробную информацию о произошедшем исключении в код внутри блока except.
rint("start") try: val = int(input("input number: ")) tmp = 10 / val print(tmp) except ValueError as ve: print("ValueError! {0}".format(ve)) except ZeroDivisionError as zde: print("ZeroDivisionError! {0}".format(zde)) except Exception as ex: print("Error! {0}".format(ex)) print("stop")
Использование finally в обработке исключений
Для выполнения определенного программного кода при выходе из блока try/except, используйте оператор finally.
try: val = int(input("input number: ")) tmp = 10 / val print(tmp) except: print("Exception") finally: print("Finally code")
Не зависимо от того, возникнет или нет во время выполнения кода в блоке try исключение, код в блоке finally все равно будет выполнен.
Если необходимо выполнить какой-то программный код, в случае если в процессе выполнения блока try не возникло исключений, то можно использовать оператор else.
try: f = open("tmp.txt", "r") for line in f: print(line) f.close() except Exception as e: print(e) else: print("File was readed")
Генерация исключений в Python
Для принудительной генерации исключения используется инструкция raise.
Самый простой пример работы с raise может выглядеть так.
try: raise Exception("Some exception") except Exception as e: print("Exception exception " + str(e))
Таким образом, можно “вручную” вызывать исключения при необходимости.
Пользовательские исключения (User-defined Exceptions) в Python
В Python можно создавать собственные исключения. Такая практика позволяет увеличить гибкость процесса обработки ошибок в рамках той предметной области, для которой написана ваша программа.
Для реализации собственного типа исключения необходимо создать класс, являющийся наследником от одного из классов исключений.
class NegValException(Exception): pass try: val = int(input("input positive number: ")) if val < 0: raise NegValException("Neg val: " + str(val)) print(val + 10) except NegValException as e: print(e)
P.S.
Если вам интересна тема анализа данных, то мы рекомендуем ознакомиться с библиотекой Pandas. На нашем сайте вы можете найти вводные уроки по этой теме. Все уроки по библиотеке Pandas собраны в книге “Pandas. Работа с данными”.
<<< Python. Урок 10. Функции в Python Python. Урок 12. Ввод-вывод данных. Работа с файлами>>>
This lesson introduces exceptions in Python. You’ll learn of the difference between syntax errors and exceptions. After a few examples, you’ll see how to raise exceptions when certain conditions are met using the raise
keyword
00:02
Hello! I’m Darren from Real Python and welcome to this video where you’re going to take a look at an introduction to Python exceptions. You’re going to see the difference between exceptions and syntax errors, how to raise an exception, the AssertionError
exception, how to handle exceptions with try
and except
, the else
clause, and using finally
. First, you’re going to take a look at the difference between exceptions and syntax errors. Here, you can see a syntax error. You can see at the end of the print statement there are two brackets where there should only be one.
00:39
If you try and run this program, the parser detects the incorrect statement, doesn’t run the program, and highlights the incorrect syntax to you. On the right of the screen, you can see an exception has happened.
00:54
You can see that the code is correct—we don’t have the extra bracket—but it’s trying to divide by zero. And if you run this program, you can see it generates a ZeroDivisionError
. Exceptions are raised when code with correct syntax results in an error.
01:13
Let’s see that in action. I’m going to be using bpython, which is a color-coded version of the Python interpreter, but if you enter these commands into the standard Python interpreter by typing python
, you’ll get the same result. Firstly, you’re going to see generating a syntax error.
01:35
There you can see you’ve got a syntax error, it says invalid syntax
, and it’s helpfully pointing to the position where the error is. It’s showing us that we’ve got an extra bracket on the end of our statement.
01:47
So that line doesn’t get executed. Now you’ll see generating an exception.
01:58
And there you can see by trying to divide by zero, a ZeroDivisionError
has been generated. Next, you’ll look at raising an exception. You can use the raise
keyword to generate an exception when a condition occurs.
02:16
Next, you’ll see a short program which will illustrate that in action.
02:37
So here on line 1 x
is set to 5
and on line 2 is compared with the value of 5
. If it’s greater than, an exception will be raised. And on line 4 there’s a print statement to show we got to the end of the program. Now at the moment if we run this, we shouldn’t see an exception because the condition on line 2 isn’t True
.
03:03
And you can see that it made it to the end. Now, let’s change the value of x
and see what the difference is. With x
set to 10
, we should get an exception.
03:19
And there it is! We just have a plain Exception
. You can also add some text at the end to help clarify why the exception was raised.
03:40
Here, the string will print out the value of x
that was passed to it, and if we run the program once more, we can see now our exception has some informative text in there.
In this article, you will learn error and exception handling in Python.
By the end of the article, you’ll know:
- How to handle exceptions using the try, except, and finally statements
- How to create a custom exception
- How to raise an exceptions
- How to use built-in exception effectively to build robust Python programs
Table of contents
- What are Exceptions?
- Why use Exception
- What are Errors?
- Syntax error
- Logical errors (Exception)
- Built-in Exceptions
- The try and except Block to Handling Exceptions
- Catching Specific Exceptions
- Handle multiple exceptions with a single except clause
- Using try with finally
- Using try with else clause
- Raising an Exceptions
- Exception Chaining
- Custom and User-defined Exceptions
- Customizing Exception Classes
- Exception Lifecycle
- Warnings
What are Exceptions?
An exception is an event that occurs during the execution of programs that disrupt the normal flow of execution (e.g., KeyError Raised when a key is not found in a dictionary.) An exception is a Python object that represents an error..
In Python, an exception is an object derives from the BaseException class that contains information about an error event that occurred within a method. Exception object contains:
- Error type (exception name)
- The state of the program when the error occurred
- An error message describes the error event.
Exception are useful to indicate different types of possible failure condition.
For example, bellow are the few standard exceptions
- FileNotFoundException
- ImportError
- RuntimeError
- NameError
- TypeError
In Python, we can throw an exception in the try block and catch it in except block.
Why use Exception
- Standardized error handling: Using built-in exceptions or creating a custom exception with a more precise name and description, you can adequately define the error event, which helps you debug the error event.
- Cleaner code: Exceptions separate the error-handling code from regular code, which helps us to maintain large code easily.
- Robust application: With the help of exceptions, we can develop a solid application, which can handle error event efficiently
- Exceptions propagation: By default, the exception propagates the call stack if you don’t catch it. For example, if any error event occurred in a nested function, you do not have to explicitly catch-and-forward it; automatically, it gets forwarded to the calling function where you can handle it.
- Different error types: Either you can use built-in exception or create your custom exception and group them by their generalized parent class, or Differentiate errors by their actual class
What are Errors?
On the other hand, An error is an action that is incorrect or inaccurate. For example, syntax error. Due to which the program fails to execute.
The errors can be broadly classified into two types:
- Syntax errors
- Logical errors
Syntax error
The syntax error occurs when we are not following the proper structure or syntax of the language. A syntax error is also known as a parsing error.
When Python parses the program and finds an incorrect statement it is known as a syntax error. When the parser found a syntax error it exits with an error message without running anything.
Common Python Syntax errors:
- Incorrect indentation
- Missing colon, comma, or brackets
- Putting keywords in the wrong place.
Example
print("Welcome to PYnative")
print("Learn Python with us..")
Output
print("Learn Python with us..")
^
IndentationError: unexpected indent
Logical errors (Exception)
Even if a statement or expression is syntactically correct, the error that occurs at the runtime is known as a Logical error or Exception. In other words, Errors detected during execution are called exceptions.
Common Python Logical errors:
- Indenting a block to the wrong level
- using the wrong variable name
- making a mistake in a boolean expression
Example
a = 10
b = 20
print("Addition:", a + c)
Output
print("Addition:", a + c)
NameError: name 'c' is not defined
Built-in Exceptions
The below table shows different built-in exceptions.
Python automatically generates many exceptions and errors. Runtime exceptions, generally a result of programming errors, such as:
- Reading a file that is not present
- Trying to read data outside the available index of a list
- Dividing an integer value by zero
Exception | Description |
---|---|
AssertionError |
Raised when an assert statement fails. |
AttributeError |
Raised when attribute assignment or reference fails. |
EOFError |
Raised when the input() function hits the end-of-file condition. |
FloatingPointError |
Raised when a floating-point operation fails. |
GeneratorExit |
Raise when a generator’s close() method is called. |
ImportError |
Raised when the imported module is not found. |
IndexError |
Raised when the index of a sequence is out of range. |
KeyError |
Raised when a key is not found in a dictionary. |
KeyboardInterrupt |
Raised when the user hits the interrupt key (Ctrl+C or Delete) |
MemoryError |
Raised when an operation runs out of memory. |
NameError |
Raised when a variable is not found in the local or global scope. |
OSError |
Raised when system operation causes system related error. |
ReferenceError |
Raised when a weak reference proxy is used to access a garbage collected referent. |
Example: The FilenotfoundError
is raised when a file in not present on the disk
fp = open("test.txt", "r")
if fp:
print("file is opened successfully")
Output:
FileNotFoundError: [Errno 2] No such file or directory: 'test.txt'
The try
and except
Block to Handling Exceptions
When an exception occurs, Python stops the program execution and generates an exception message. It is highly recommended to handle exceptions. The doubtful code that may raise an exception is called risky code.
To handle exceptions we need to use try and except block. Define risky code that can raise an exception inside the try
block and corresponding handling code inside the except
block.
Syntax
try :
# statements in try block
except :
# executed when exception occured in try block
The try block is for risky code that can raise an exception and the except block to handle error raised in a try block. For example, if we divide any number by zero, try block will throw ZeroDivisionError
, so we should handle that exception in the except block.
When we do not use try…except
block in the program, the program terminates abnormally, or it will be nongraceful termination of the program.
Now let’s see the example when we do not use try…except
block for handling exceptions.
Example:
a = 10
b = 0
c = a / b
print("a/b = %d" % c)
Output
Traceback (most recent call last):
File "E:/demos/exception.py", line 3, in <module>
c = a / b
ZeroDivisionError: division by zero
We can see in the above code when we are divided by 0; Python throws an exception as ZeroDivisionError
and the program terminated abnormally.
We can handle the above exception using the try…except
block. See the following code.
Example
try:
a = 10
b = 0
c = a/b
print("The answer of a divide by b:", c)
except:
print("Can't divide with zero. Provide different number")
Output
Can't divide with zero. Provide different number
Catching Specific Exceptions
We can also catch a specific exception. In the above example, we did not mention any specific exception in the except block. Catch all the exceptions and handle every exception is not good programming practice.
It is good practice to specify an exact exception that the except clause should catch. For example, to catch an exception that occurs when the user enters a non-numerical value instead of a number, we can catch only the built-in ValueError exception that will handle such an event properly.
We can specify which exception except
block should catch or handle. A try
block can be followed by multiple numbers of except
blocks to handle the different exceptions. But only one exception will be executed when an exception occurs.
Example
In this example, we will ask the user for the denominator value. If the user enters a number, the program will evaluate and produce the result.
If the user enters a non-numeric value then, the try block will throw a ValueError
exception, and we can catch that using a first catch block ‘except ValueError’ by printing the message ‘Entered value is wrong’.
And suppose the user enters the denominator as zero. In that case, the try block will throw a ZeroDivisionError
, and we can catch that using a second catch block by printing the message ‘Can’t divide by zero’.
try:
a = int(input("Enter value of a:"))
b = int(input("Enter value of b:"))
c = a/b
print("The answer of a divide by b:", c)
except ValueError:
print("Entered value is wrong")
except ZeroDivisionError:
print("Can't divide by zero")
Output 1:
Enter value of a:Ten Entered value is wrong
Output 2:
Enter value of a:10 Enter value of b:0 Can't divide by zero
Output 3:
Enter value of a:10 Enter value of b:2 The answer of a divide by b: 5.0
Handle multiple exceptions with a single except clause
We can also handle multiple exceptions with a single except
clause. For that, we can use an tuple
of values to specify multiple exceptions in an except
clause.
Example
Let’s see how to specifiy two exceptions in the single except clause.
try:
a = int(input("Enter value of a:"))
b = int(input("Enter value of b:"))
c = a / b
print("The answer of a divide by b:", c)
except(ValueError, ZeroDivisionError):
print("Please enter a valid value")
Using try
with finally
Python provides the finally
block, which is used with the try block statement. The finally
block is used to write a block of code that must execute, whether the try
block raises an error or not.
Mainly, the finally
block is used to release the external resource. This block provides a guarantee of execution.
Clean-up actions using finally
Sometimes we want to execute some action at any cost, even if an error occurred in a program. In Python, we can perform such actions using a finally statement with a try and except statement.
The block of code written in the finally block will always execute even there is an exception in the try and except block.
If an exception is not handled by except clause, then finally block executes first, then the exception is thrown. This process is known as clean-up action.
Syntax
try:
# block of code
# this may throw an exception
finally:
# block of code
# this will always be executed
# after the try and any except block
Example
try:
a = int(input("Enter value of a:"))
b = int(input("Enter value of b:"))
c = a / b
print("The answer of a divide by b:", c)
except ZeroDivisionError:
print("Can't divide with zero")
finally:
print("Inside a finally block")
Output 1:
Enter value of a:20 Enter value of b:5 The answer of a divide by b: 4.0 Inside a finally block
Output 2:
Enter value of a:20 Enter value of b:0 Can't divide with zero Inside a finally block
In the above example, we can see we divide a number by 0 and get an error, and the program terminates normally. In this case, the finally
block was also executed.
Using try
with else
clause
Sometimes we might want to run a specific block of code. In that case, we can use else
block with the try-except
block. The else
block will be executed if and only if there are no exception is the try
block. For these cases, we can use the optional else
statement with the try
statement.
Why to use else
block with try?
Use else statemen with try block to check if try block executed without any exception or if you want to run a specific code only if an exception is not raised
Syntax
try:
# block of code
except Exception1:
# block of code
else:
# this code executes when exceptions not occured
try
: Thetry
block for risky code that can throw an exception.except
: Theexcept
block to handle error raised in atry
block.else
: Theelse
block is executed if there is no exception.
Example
try:
a = int(input("Enter value of a:"))
b = int(input("Enter value of b:"))
c = a / b
print("a/b = %d" % c)
except ZeroDivisionError:
print("Can't divide by zero")
else:
print("We are in else block ")
Output 1
Enter value of a: 20 Enter value of b:4 a/b = 5 We are in else block
Output 2
Enter value of a: 20 Enter value of b:0 Can't divide by zero
Raising an Exceptions
In Python, the raise
statement allows us to throw an exception. The single arguments in the raise
statement show an exception to be raised. This can be either an exception object or an Exception
class that is derived from the Exception
class.
The raise
statement is useful in situations where we need to raise an exception to the caller program. We can raise exceptions in cases such as wrong data received or any validation failure.
Follow the below steps to raise an exception:
- Create an exception of the appropriate type. Use the existing built-in exceptions or create your won exception as per the requirement.
- Pass the appropriate data while raising an exception.
- Execute a raise statement, by providing the exception class.
The syntax to use the raise
statement is given below.
raise Exception_class,<value>
Example
In this example, we will throw an exception if interest rate is greater than 100.
def simple_interest(amount, year, rate):
try:
if rate > 100:
raise ValueError(rate)
interest = (amount * year * rate) / 100
print('The Simple Interest is', interest)
return interest
except ValueError:
print('interest rate is out of range', rate)
print('Case 1')
simple_interest(800, 6, 8)
print('Case 2')
simple_interest(800, 6, 800)
Output:
Case 1 The Simple Interest is 384.0 Case 2 interest rate is out of range 800
Exception Chaining
The exception chaining is available only in Python 3. The raise
statements allow us as optional from
statement, which enables chaining exceptions. So we can implement exception chaining in python3 by using raise…from
clause to chain exception.
When exception raise, exception chaining happens automatically. The exception can be raised inside except
or finally
block section. We also disabled exception chaining by using from None
idiom.
Example
try:
a = int(input("Enter value of a:"))
b = int(input("Enter value of b:"))
c = a/b
print("The answer of a divide by b:", c)
except ZeroDivisionError as e:
raise ValueError("Division failed") from e
# Output: Enter value of a:10
# Enter value of b:0
# ValueError: Division failed
In the above example, we use exception chaining using raise...from
clause and raise ValueError
division failed.
Custom and User-defined Exceptions
Sometimes we have to define and raise
exceptions explicitly to indicate that something goes wrong. Such a type of exception is called a user-defined exception or customized exception.
The user can define custom exceptions by creating a new class. This new exception class has to derive either directly or indirectly from the built-in class Exception
. In Python, most of the built-in exceptions also derived from the Exception
class.
class Error(Exception):
"""Base class for other exceptions"""
pass
class ValueTooSmallError(Error):
"""Raised when the input value is small"""
pass
class ValueTooLargeError(Error):
"""Raised when the input value is large"""
pass
while(True):
try:
num = int(input("Enter any value in 10 to 50 range: "))
if num < 10:
raise ValueTooSmallError
elif num > 50:
raise ValueTooLargeError
break
except ValueTooSmallError:
print("Value is below range..try again")
except ValueTooLargeError:
print("value out of range...try again")
print("Great! value in correct range.")
Output
Enter any value in 10 to 50 range: 5
Value is below range..try again
Enter any value in 10 to 50 range: 60
value out of range...try again
Enter any value in 10 to 50 range: 11
Great! value in correct range.
In the above example, we create two custom classes or user-defined classes with names, ValueTooSmallError
and ValueTooLargeError
.When the entered value is below the range, it will raise ValueTooSmallError
and if the value is out of then, it will raise
ValueTooLargeError
.
Customizing Exception Classes
We can customize the classes by accepting arguments as per our requirements. Any custom exception class must be Extending from BaseException
class or subclass of BaseException
.
In the above example, we create a custom class that is inherited from the base class Exception
. This class takes one argument age. When entered age is negative, it will raise NegativeAgeError
.
class NegativeAgeError(Exception):
def __init__(self, age, ):
message = "Age should not be negative"
self.age = age
self.message = message
age = int(input("Enter age: "))
if age < 0:
raise NegativeAgeError(age)
# Output:
# raise NegativeAgeError(age)
# __main__.NegativeAgeError: -9
Output:
Enter age: -28 Traceback (most recent call last): File "E:/demos/exception.py", line 11, in raise NegativeAgeError(age) main.NegativeAgeError: -28
Done
Exception Lifecycle
- When an exception is raised, The runtime system attempts to find a handler for the exception by backtracking the ordered list of methods calls. This is known as the call stack.
- If a handler is found (i.e., if
except
block is located), there are two cases in theexcept
block; either exception is handled or possibly re-thrown. - If the handler is not found (the runtime backtracks to the method chain’s last calling method), the exception stack trace is printed to the standard error console, and the application stops its execution.
Example
def sum_of_list(numbers):
return sum(numbers)
def average(sum, n):
# ZeroDivisionError if list is empty
return sum / n
def final_data(data):
for item in data:
print("Average:", average(sum_of_list(item), len(item)))
list1 = [10, 20, 30, 40, 50]
list2 = [100, 200, 300, 400, 500]
# empty list
list3 = []
lists = [list1, list2, list3]
final_data(lists)
Output
Average: 30.0 Traceback (most recent call last): File "E:/demos/exceptions.py", line 17, in final_data(lists) File "E:/demos/exceptions.py", line 11, in final_data print("Average:", average(sum_of_list(item), len(item))) Average: 300.0 File "E:/demos/exceptions.py", line 6, in average return sum / n ZeroDivisionError: division by zero
The above stack trace shows the methods that are being called from main() until the method created an exception condition. It also shows line numbers.
Warnings
Several built-in exceptions represent warning categories. This categorization is helpful to be able to filter out groups of warnings.
The warning doesn’t stop the execution of a program it indicates the possible improvement
Below is the list of warning exception
Waring Class | Meaning |
---|---|
Warning | Base class for warning categories |
UserWarning | Base class for warnings generated by user code |
DeprecationWarning | Warnings about deprecated features |
PendingDeprecationWarning | Warnings about features that are obsolete and expected to be deprecated in the future, but are not deprecated at the moment. |
SyntaxWarning | Warnings about dubious syntax |
RuntimeWarning | Warnings about the dubious runtime behavior |
FutureWarning | Warnings about probable mistakes in module imports |
ImportWarning | Warnings about probable mistakes in module imports |
UnicodeWarning | Warnings related to Unicode data |
BytesWarning | Warnings related to bytes and bytearray. |
ResourceWarning | Warnings related to resource usage |
Генерация исключений и создание своих типов исключений
Последнее обновление: 30.01.2022
Генерация исключений и оператор raise
Иногда возникает необходимость вручную сгенерировать то или иное исключение. Для этого применяется оператор raise. Например, сгенерируем исключение
try: number1 = int(input("Введите первое число: ")) number2 = int(input("Введите второе число: ")) if number2 == 0: raise Exception("Второе число не должно быть равно 0") print("Результат деления двух чисел:", number1/number2) except ValueError: print("Введены некорректные данные") except Exception as e: print(e) print("Завершение программы")
Оператору raise передается объект BaseException — в данном случае объект Exception. В конструктор
этого типа можно ему передать сообщение, которое затем можно вывести пользователю. В итоге, если number2 будет равно 0, то сработает оператор
raise, который сгенерирует исключение. В итоге управление программой перейдет к блоку except, который обрабатывает
исключения типа Exception:
Введите первое число: 1 Введите второе число: 0 Второе число не должно быть равно 0 Завершение программы
Создание своих типов исключений
В языке Python мы не ограничены только встроенными типами исключений и можем, применяя наследование, при необходимости создавать свои
типы исключений. Например, возьмем следующий класс Person:
class Person: def __init__(self, name, age): self.__name = name # устанавливаем имя self.__age = age # устанавливаем возраст def display_info(self): print(f"Имя: {self.__name} Возраст: {self.__age}")
Здесь класс Person в конструкторе получает значения для имени и возраста и присваивает их приватным переменным name и age.
Однако при создании объекта Person мы можем передать в конструктор некорректное с точки зрения логики значение — например, отрицательное число.
Одним из способов решения данной ситуации представляет генерация исключения при передаче некорректных значений.
Итак, определим следующий код программы:
class PersonAgeException(Exception): def __init__(self, age, minage, maxage): self.age = age self.minage = minage self.maxage = maxage def __str__(self): return f"Недопустимое значение: {self.age}. " f"Возраст должен быть в диапазоне от {self.minage} до {self.maxage}" class Person: def __init__(self, name, age): self.__name = name # устанавливаем имя minage, maxage = 1, 110 if minage < age < maxage: # устанавливаем возраст, если передано корректное значение self.__age = age else: # иначе генерируем исключение raise PersonAgeException(age, minage, maxage) def display_info(self): print(f"Имя: {self.__name} Возраст: {self.__age}") try: tom = Person("Tom", 37) tom.display_info() # Имя: Tom Возраст: 37 bob = Person("Bob", -23) bob.display_info() except PersonAgeException as e: print(e) # Недопустимое значение: -23. Возраст должен быть в диапазоне от 1 до 110
В начале здесь определен класс PersonAgeException, который наследуется от класса Exception. Как правило, собственные классы исключений
наследуются от класса Exception. Класс PersonAgeException предназначен для исключений, связанных с возрастом пользователя.
В конструкторе PersonAgeException получаем три значения — собственное некорректное значение, которое послужило причиной исключения,
а также минимальное и максимальное значения возраста.
class PersonAgeException(Exception): def __init__(self, age, minage, maxage): self.age = age self.minage = minage self.maxage = maxage def __str__(self): return f"Недопустимое значение: {self.age}. " f"Возраст должен быть в диапазоне от {self.minage} до {self.maxage}"
В функции __str__ определяем текстовое представление класса — по сути сообщение об ошибке.
В конструкторе класса Persoon проверяем переданное для возраста пользователя значение. И если это значение не соответствует
определенному диапазону, то генерируем исключение типа PersonAgeException:
raise PersonAgeException(age, minage, maxage)
При применении класса Person нам следует учитывать, что конструктор класса может сгенерировать исключение при передаче некорректного
значения. Поэтому создание объектов Person обертывается в конструкцию try..except:
try: tom = Person("Tom", 37) tom.display_info() # Имя: Tom Возраст: 37 bob = Person("Bob", -23) # генерируется исключение типа PersonAgeException bob.display_info() except PersonAgeException as e: print(e) # Недопустимое значение: -23. Возраст должен быть в диапазоне от 1 до 110
И если при вызове конструктора Person будет сгенерировано исключение типа PersonAgeException, то управление программой перейдет к
блоку except, который обрабатывает исключения типа PersonAgeException в виде вывода информации об исключении на консоль.
Introduction to Python Throw Exception
The following article provides an outline for Python Throw Exception. Python returns an error or exceptions sometimes when there is no programmatic or syntax mistake in our program, sometimes wrong input also generates an exception like division of two numbers will not return an exception, but the number is divided by zero will return an exception. So we need to do proper exception handling, and we need to detect which part of our program can return an exception, and we can surround that part with the try-catch block and return a proper exception to the user so that he can identify that program arose during program execution.
Raising Exceptions
We can use the raise keyword and name of the exception to forcefully throw an exception by python. We can also pass any message inside the exception or simply write an exception name.
Example #1
Code:
raise NameError("Hello")
Output:
As you can see, python has returned a NameError exception with a Hello message. We can also generate exceptions without any message.
Example #2
Code:
raise NameError
Output:
As you can see, that exception is generated, but it is not good. So we can try to catch this exception and try to display a custom message when such an exception occurs during program execution.
Example #3
Code:
try:
raise NameError('Hello')
except NameError:
print('Sorry Exception is generated')
Output:
In this example, you can see that we have written our code in the try block. We write their piece of code that might return an exception in the try block and catch that exception in a catch block. We have defined the except block and defined the name of the exception that we are looking for. If the program returns that exception, then we return a custom message to the user, and it looks more clean and promising than the default python exception.
User-Defined Exceptions
The user defines these types of exceptions by making class. Generally, exceptions are inherited from the Exception class. This class is very similar to other custom classes that we make in our programs. We can write anything inside these classes, but it’s good to practice to keep it very simple and define only the required attributes or variables or information that will be needed by exception handlers.
Example #1
Code:
class failedException(Exception):
def __init__(self):
super()
try:
marks = 35
print("Your marks are: "+str(marks))
if marks<36:
raise failedException
except failedException:
print("Sorry! You are failed!")
else:
print("Congratulations! You are passed")
Output:
In the above program, you can see that we have defined our class failedException. You can define any name as per your wish. We are inheriting the exception class. We have defined inside it and used the constructor; we call base class methods, i.e. super(). We have created a try block, and then we have defined a variable mark with a value of 35. First, we are just printing the message and value of the variable. Then we are checking if the value is less than 36, then we are raising the exception.
We can write any name for the exception as it is user-defined. Then we have defined except that is catching our exception and printing defined message and in else condition, we have defined another message. When our condition is failed, then our defined exception is called, and a message is printed.
Example #2
Code:
class MarksRange(Exception):
def __init__(self, marks, message="You are failed!"):
self.marks = marks
self.message = message
super().__init__(self.message)
def __str__(self):
return f'{self.marks} -> {self.message}'
marks = int(input("Enter marks: "))
if not marks > 36:
raise MarksRange(marks)
Output:
In this above program, we have created a custom class MarksRange and inherited the Base Class Exception.
We have defined a constructor inside the class and passed self, marks, and message variables that are holding our values. We are overriding our constructor with our custom arguments, i.e. marks and messages. We are manually calling the exception of the parent class with self-parameter marks and messages using super().
We are using __str__ for displaying the exception of the class and the message we have defined, and our exception MarksRange will be raised. Python will ask the user to input the marks then check if the marks are less than 36. If the condition matches, then we are raising the exception; if the condition doest match, nothing will happen. When we are creating a large python program, it is always a good practice to keep custom user-defined exceptions in a separate file; it’s a kind of standard process that is followed. We can name our exception file as exception.py or error.py also.
Conclusion – Python Throw Exception
User-Defined exceptions are the exceptions that the user defines to handle some error scenario that is not inbuilt. We want to make custom exceptions and show them accordingly to the user end.
Recommended Articles
This is a guide to Python Throw Exception. Here we discuss the introduction, raising, and user-defined exceptions along with examples respectively. You may also have a look at the following articles to learn more –
- Python Stream
- Python BufferedReader
- Python Dump
- Python write CSV file