# Exception Handling in Python

Dec. 15, 2020 269

In Python, errors are generally of two types: syntax errors and exceptions. When a syntax error occurs, the program fails to execute, and the parser shows where the error occurred. Consider the following example.

print("This statement causes a syntax error)


Output

Exceptions, on the other hand, are the errors that occur when a syntactically correct code runs into a problem during its execution. If an exception is not handled, then the program crashes. The error message is shown consisting of the exception type, details, and the context where it happened.

print("my name is " + name)


## The try and except block

However, we can write programs that handle exceptions. We can do it by using try and except statements. The try block contains the code that can throw an exception. The except clause handles the exception that occurs in the try clause.

An except statement optionally takes an exception type, which follows the except keyword. If an exception type is provided, then that block gets executed only if the raised exception matches the specified type. If no exception type is provided, then that except clause gets executed for any type. This, however, is not recommended, as it does not give information about the raised exception.

Consider the following example, where we divide two numbers. Now, there is a possibility that a number can be divided by zero, and hence, ZeroDivisionError exception can occur. Therefore, we put the suspicious code in the try block. We also add an except block to handle that exception.

a = 12
b = 12
try:
result = a / b
print(f"The result of the division is: {result}")
except ZeroDivisionError:
print("Division by zero is undefined")

print("End Program")


Output

​The result of the division is: 1.0
End Program

Here, the variable b has a non-zero value. Therefore, no exception gets raised. The try clause executes without any interruption, and no except clause runs.

a = 12
b = 0
try:
result = a / b
print(f"The result of the division is: {result}")
except ZeroDivisionError:
print("Division by zero is undefined")

print("End Program")


Output

Division by zero is undefined
End Program

Now, the variable b has a zero value. So, the ZeroDivisionError exception occurs at line 4, and no lines in the try clause get executed after that. Since an except clause exists that handles the ZeroDivisionError exception, it gets executed. After this, statements after the try and except blocks run. If an exception is not handled either by any current or outer except clause, then the program’s execution is interrupted, and the error message gets displayed.

## Multiple except clauses

A try statement can have multiple except statements. However, only one executes at one time. Let’s take an example.

a = 12
b = "2"
try:
result = a / b
print(f"The result of the division is: {result}")
except ZeroDivisionError:
print("Division by zero is undefined")
except NameError:
except TypeError:
print(
"Please make sure that the variable types are supported for division operation"
)
except:
print("Unexpected error")

print("End Program")


Output

​Please make sure that the variable types are supported for division operation
End Program

The above code contains different except statements to handle various exceptions. Since we are attempting to divide a number by a string value, we get a TypeError exception, which gets handled in the corresponding except clause. Here, we also have a generic except block that does not contain any exception type and handles exceptions other than the specified ones. Remember that you must put the default except statement after all the other except statements. Otherwise, you will get a syntax error.

## An except clause with multiple exception types

You can also have an except clause that handles multiple exceptions. This is useful when you want to run the same type of statements for different exception types.

a = 12
b = "2"
try:
result = a / b
print(f"The result of the division is: {result}")
except (ZeroDivisionError, NameError, TypeError):
print("Error Message: Make sure that both operands are valid")

print("End Program")


Output

​Error Message: Make sure that both operands are valid
End Program

## The else clause

The else clause comes after all the except statements. It only runs when no exception occurs in the try block.

a = 12
b = "2"
try:
result = a / b
print(f"The result of the division is: {result}")
except ZeroDivisionError:
print("Division by zero is undefined")
except NameError:
except TypeError:
print(
"Please make sure that the variable types are supported for division operation"
)
except:
print("Unexpected error")
else:
print("division performed successfully")

print("End Program")


Output

​Please make sure that the variable types are supported for division operation
End Program

As you can see above, the else clause does not run when an exception gets raised.

a = 12
b=2
try:
result = a/b
print(f"The result of the division is: {result}")
except ZeroDivisionError:
print("Division by zero is undefined")
except NameError:
except TypeError:
print("Please make sure that the variable types are supported for division operation")
except:
print("Unexpected error")
else:
print("division performed successfully")

print("End Program")


Output

​The result of the division is: 6.0
division performed successfully
End Program

Since the try block runs without any interruption, the else clause gets executed.

## The exception’s argument

The exception’s argument is a value that gives us information about the exception. To get that additional info, add a variable after the exception type in the except statement. The contents and the presence of the argument depend upon the type of exception. Let’s see.

Consider the example in which we try to read a file that does not exist.

try:
f = open("sample.txt", "r")
except FileNotFoundError as arg:
print(type(arg))
print(arg)
else:


Output

​<class 'FileNotFoundError'>
[Errno 2] No such file or directory: 'sample.txt'

## The finally clause

While the else clause executes when the try clause does not raise any exception, the finally clause runs whether or not an exception occurs in the try block. Therefore, it is used to define clean-up actions such as closing files, releasing resources, etc.

Consider the following example.

try:
f = open("sample.txt", "r")
except FileNotFoundError as arg:
print(arg)
else:
finally:
print("finally clause")


Output

[Errno 2] No such file or directory: 'sample.txt'
finally clause

In the above example, we again try to read a file that does not exist. Therefore, the FileNotFoundError exception gets raised. Since we handle that type, the corresponding clause runs. After that, the finally clause runs. If we don't handle it, the exception will be re-thrown after the finally clause finishes its execution.

try:
f = open("sample.txt", "r")
except TypeError as arg:
print(arg)
else:
finally:
print("finally clause")


Output

Let’s see the output when no exception occurs, i.e., we create a new sample.txt file.

try:
f = open("sample.txt", "r")
print("Contents of the file are:")
except FileNotFoundError as arg:
print(arg)
else:
finally:
print("finally clause")


Output

​Contents of the file are:
This is a sample file.
finally clause

Note that, if the try block (or any other) contains a return statement or a break statement, the finally clause still runs.

## Throw an exception

You can throw an exception by yourself using the raise keyword, which is followed by the exception that you want to throw.

distance = -4
try:
if distance < 0:
raise ValueError  # or ValueError()
else:
print("the distance covered is {distance} km")
except ValueError:
print("Distance can't be negative")


Output

​Distance can't be negative

If you want to pass additional information, then:

distance = -4
try:
if distance < 0:
raise ValueError("Distance can't be negative")
else:
print("the distance covered is {distance} km")
except ValueError as arg:
print(arg)


Output

​Distance can't be negative

## User-defined Exceptions

You can also create custom exceptions in Python. The custom exception class should be derived from the Exception class, directly or indirectly.

Let’s create a class that raises an exception when the score of the student is not between 0 and 100. Let’s see.

class OutOfRange(Exception):
def __init__(self, msg="Score is not in the valid range, i.e., 0-100"):
self.msg = msg
super().__init__(self.msg)

score = 400
try:
if not (score >= 0 and score <=100):
raise OutOfRange
print(f"the score of the student is {score}")
except OutOfRange as arg:
print(arg)


Output

​Score is not in the valid range, i.e., 0-100

Liked the post?
A computer science student having interest in web development. Well versed in Object Oriented Concepts, and its implementation in various projects. Strong grasp of various data structures and algorithms. Excellent problem solving skills.
Editor's Picks
0 COMMENT