Showing posts with label Python exception handling. Show all posts
Showing posts with label Python exception handling. Show all posts

Wednesday, February 5, 2020

User-defined Exceptions in Python

In this Python Exception Handling Tutorial series we'll see how to write user defined exceptions in Python.

Though Python has many built-in exception covering a lot of error scenarios but sometimes you as a user would want to create your own exception for a specific scenario in order to make error messages more relevant to the context. Such exceptions are called user-defined exceptions or custom exceptions.

User-defined exception in Python

To create a custom exception in Python you need to create a new exception class. That custom exception class should typically be derived from the Exception class (built in Exception class), either directly or indirectly.

Since your exception class is a class it can theoretically be defined to do anything any other class can do, but usually user-defined exception classes are kept simple, often only offering a number of attributes that allow information about the error to be extracted by handlers for the exception.

As a convention your custom exception should be defined with name that end in “Error”, similar to the naming of the standard exceptions.

User-defined exception Python example

Suppose you have a Python function that take age as a parameter and tells whether a person is eligible to vote or not. Voting age is 18 or more.

If person is not eligible to vote you want to raise an exception using raise statement, for this scenario you want to write a custom exception named “InvalidAgeError”.

# Custom exception
class InvalidAgeError(Exception):
  def __init__(self, arg):
    self.msg = arg

def vote_eligibility(age):
  if age < 18:
    raise InvalidAgeError("Person not eligible to vote, age is " + str(age))
  else:
    print('Person can vote, age is', age)

# calling function
try:
  vote_eligibility(22)
  vote_eligibility(14)
except InvalidAgeError as error:
  print(error)

Output

Person can vote, age is 22
Person not eligible to vote, age is 14

Hierarchical custom exceptions

When creating a module that can raise several distinct errors, a common practice is to create a base class for exceptions defined by that module, and subclass that to create specific exception classes for different error conditions:

class Error(Exception):
  """Base class for exceptions in this module."""
  pass

class InputError(Error):
  """Exception raised for errors in the input.

  Attributes:
    expression -- input expression in which the error occurred
    message -- explanation of the error
  """

  def __init__(self, expression, message):
    self.expression = expression
    self.message = message

That's all for this topic User-defined Exceptions in Python. If you have any doubt or any suggestions to make please drop a comment. Thanks!

>>>Return to Python Tutorial Page


Related Topics

  1. Python Exception Handling - try,except,finally
  2. Python assert Statement
  3. Passing Object of The Class as Parameter in Python
  4. Name Mangling in Python
  5. Strings in Python With Method Examples

You may also like-

  1. Magic Methods in Python With Examples
  2. Getting Substring in Python String
  3. Variable Length Arguments (*args), Keyword Varargs (**kwargs) in Python
  4. Python Program to Display Prime Numbers
  5. HashSet in Java With Examples
  6. Java Multithreading Interview Questions And Answers
  7. Switch-Case Statement in Java
  8. Spring Email Scheduling Example Using Quartz Scheduler

Tuesday, February 4, 2020

raise Statement in Python Exception Handling

In Python Exception Handling - try,except,finally we saw some examples of exception handling in Python but exceptions, in all the examples there, were thrown automatically. You can throw an exception manually too using raise statement in Python.

Python raise statement

For throwing an exception using raise there are the following options-

1. You can simply use raise without any other expression. If no expressions are present, raise re-raises the last exception that was active in the current scope. If no exception is active in the current scope, a RuntimeError exception is raised indicating that this is an error.

def divide_num(num1, num2):
  try:
    print('Result-',num1/num2)
  except ZeroDivisionError as error:
    print('Zero is not a valid argument here')
    #raise with no expression
    raise

divide_num(10, 0)

Output

Zero is not a valid argument here
Traceback (most recent call last):
  File "F:/NETJS/NetJS_2017/Python/Programs/Test.py", line 10, in <module>
    divide_num(10, 0)
  File "F:/NETJS/NetJS_2017/Python/Programs/Test.py", line 3, in divide_num
    print('Result-',num1/num2)
ZeroDivisionError: division by zero

As you can see raise statement re-raises the last exception again.

2. If raise is used with an expression then raise evaluates the first expression as the exception object. It must be either a subclass or an instance of BaseException. If it is a class, the exception instance will be obtained when needed by instantiating the class with no arguments.

def divide_num(num1, num2):
  try:
    print('Result-',num1/num2)
  except ZeroDivisionError as error:
    print('Zero is not a valid argument here')
    raise RuntimeError("An error occurred")

divide_num(10, 0)

Output

Zero is not a valid argument here
Traceback (most recent call last):
  File "F:/NETJS/NetJS_2017/Python/Programs/Test.py", line 3, in divide_num
    print('Result-',num1/num2)
ZeroDivisionError: division by zero

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "F:/NETJS/NetJS_2017/Python/Programs/Test.py", line 9, in <module>
    divide_num(10, 0)
  File "F:/NETJS/NetJS_2017/Python/Programs/Test.py", line 6, in divide_num
    raise RuntimeError("An error occurred")
RuntimeError: An error occurred

As you can see in this case previous exception is attached as the new exception’s __context__ attribute.

3. raise can also be used with from clause for exception chaining. With the from clause another exception class or instance is given, which will then be attached to the raised exception as the __cause__ attribute.

In the example there are two functions, from function func() there is a call to function divide_num with arguments that cause ZeroDivisionError.

def divide_num(num1, num2):
  try:
    print('Result-',num1/num2)
  except ZeroDivisionError as error:
    print('Zero is not a valid argument here')
    raise RuntimeError("An error occurred") from error

def func():
  try:
    divide_num(10, 0)
  except RuntimeError as obj:
    print(obj)
    print(obj.__cause__)

func()

Output

Zero is not a valid argument here
An error occurred
division by zero

As you can see using __cause__ attribute you can get the attached exception.

That's all for this topic raise Statement in Python Exception Handling. If you have any doubt or any suggestions to make please drop a comment. Thanks!

>>>Return to Python Tutorial Page


Related Topics

  1. User-defined Exceptions in Python
  2. Passing Object of The Class as Parameter in Python
  3. Encapsulation in Python
  4. Interface in Python
  5. Python break Statement With Examples

You may also like-

  1. Magic Methods in Python With Examples
  2. Check if String Present in Another String in Python
  3. Default Arguments in Python
  4. Python Program to Display Armstrong Numbers
  5. HashMap in Java With Examples
  6. this Keyword in Java With Examples
  7. Introduction to Hadoop Framework
  8. Spring Web Reactive Framework - Spring WebFlux Tutorial

Monday, February 3, 2020

Python Exception Handling - try,except,finally

In this article we’ll see how to handle exceptions in Python using try, except and finally statements.

Python exception handling

To handle exception in Python you can use the following procedure-

  1. Use try block to enclose code that might throw an exception.
  2. Use except block to handle the raised exceptions.
  3. Use finally clause to perform clean up like closing the opened file.

General form of exception handling in Python using try, except finally is as follows.

try: 
 try suite
               
except Exception1:
 handler suite
except Exception2:
 handler suite
else:
 else suite
finally: 
 finally suite

Some important points to note here are-

  1. If no exception is raised then the statements in the else block are executed.
  2. Else and finally blocks are not mandatory.
  3. You can have multiple except blocks to handle multiple exceptions.
  4. try block must be followed either by except or finally.
  5. If finally block is there it is always executed whether an exception is raised or not.

Using try, except for exception handling

Let’s try to understand how exception handling in Python using try and except helps in writing robust code. Here is an example where a list is passed to a function and every element in the list is used to divide a number. Just notice what happens if one of the number in the list is zero.

def divide_num(num_list):
  for num in num_list:
    print(10/num)

num_list = [5, 6, 0, 7]
divide_num(num_list)

Output

2.0
1.6666666666666667
Traceback (most recent call last):

  File "F:/NETJS/NetJS_2017/Python/Test/Test.py", line 6, in <module>
    divide_num(num_list)
  File "F:/NETJS/NetJS_2017/Python/Test/Test.py", line 3, in divide_num
    print(10/num)
ZeroDivisionError: division by zero

As you can see dividing by zero raises ZeroDivisionError, since code doesn’t provide any exception handling code of its own so default exception handling is used. Default behavior for handling such exceptions in Python is for the interpreter to print the full stack traceback, that includes the exception type (at least in case of built-in exception) and error message, and then terminate the program.

As you can see program is terminated and only the exception message is displayed by the default exception handling which is not that user friendly.

Python exception handling with try, except

Now let’s write that same code by providing exception handling with in the code using try and except.

def divide_num(num_list):
  for num in num_list:
    try:
      print(10/num)
    except ZeroDivisionError as error:
      print(error)
      print('Zero is not a valid argument here')
    else:
      print('in else block')

num_list = [5, 6, 0, 7]
divide_num(num_list)

Output

2.0
in else block
1.6666666666666667
in else block
division by zero
Zero is not a valid argument here
1.4285714285714286
in else block

As you can see now the code that may throw an exception is enclosed with in a try block. When the exception is raised in the try block exception handler looks for the except block that can handle the exception of that type. In the code ZeroDivisionError is raised and there is an except block that handles ZeroDivisionError so that except block handles the raised exception. Program is not terminated now when the exception is raised because of the exception handling in the code.

except block in Python

There are various ways to write except block while writing exception handling code in Python.

  1. You can catch the exception as an object that gives description about the raised exception.
     except ZeroDivisionError as error:
     
  2. You can write except block with the exception class name only.
     except Exception_Class_Name:
     
  3. You can handle multiple exceptions by using multiple except blocks or you can use a single except block and write multiple exceptions as a tuple.

    For example multiple except blocks-

    except ZeroDivisionError as error:
      print(error)
      print('Zero is not a valid argument here')
    except TypeError:
      print('Argument is not of valid type') 
      

    Single except block with multiple exceptions

      except (ZeroDivisionError, TypeError):
      
  4. You can write except with out specifying exception class. That way except block catches any type of exception. Though that is not considered good practice as it is too broad exception clause and you won’t be able to determine specifically which exception has been raised.
      except:
        print('An exception has occurred')
      

Multiple except block Python example

def divide_num(num_list):
  for num in num_list:
    try:
      print(10/num)
    except ZeroDivisionError as error:
      print(error)
      print('Zero is not a valid argument here')
    except TypeError as error:
      print(error)
      print('Argument is not of valid type-', num)

num_list = [5, 6, 'a', 7]
divide_num(num_list)

Output

2.0
1.6666666666666667
unsupported operand type(s) for /: 'int' and 'str'
Argument is not of valid type- a
1.4285714285714286

finally in Python exception handling

If finally is present, it specifies a ‘cleanup’ handler. The finally clause is always executed whether an exception is raised in the try block or not. That ensures that all the resources are properly cleaned up.

def divide_num(num):
  try:
    f = open("testfile", "a")
    r = 10/num
    f.write("Result 10/%d is %d" %(num,r))
  except ZeroDivisionError as error:
    print(error)
    print('Zero is not a valid argument here')
  except FileNotFoundError as error:
    print(error)
    print('Passed file does not exist')

  finally:
    print('closing file')
    f.close()

divide_num(0)

Output

division by zero
Zero is not a valid argument here
closing file

If function is called with a valid argument and no exception is raised even then finally block is executed. For example calling function as given here.

divide_num(2)

Output

closing file

If there is a return, break or continue statement in try block even then finally clause is executed.

def divide_num():
  try:
    return 'try'
  finally:
    print('In finally clause')

a = divide_num()
print(a)

Output

In finally clause
try

If there is a return statement in finally too then that becomes the last return statement to be executed. Since the return value of a function is determined by the last return statement executed so value returned by finally clause is the value returned by the function.

def divide_num():
  try:
    return 'try'
  finally:
    print('In finally clause')
    return 'finally'

a = divide_num()
print(a)

Output

In finally clause
finally

That's all for this topic Python Exception Handling - try,except,finally. If you have any doubt or any suggestions to make please drop a comment. Thanks!

>>>Return to Python Tutorial Page


Related Topics

  1. raise Statement in Python Exception Handling
  2. Passing Object of The Class as Parameter in Python
  3. Encapsulation in Python
  4. Abstract Class in Python
  5. Strings in Python With Method Examples

You may also like-

  1. Magic Methods in Python With Examples
  2. Check if String Present in Another String in Python
  3. Keyword Arguments in Python
  4. Python Program to Display Fibonacci Series
  5. Java Collections Interview Questions And Answers
  6. this Keyword in Java With Examples
  7. What is Hadoop Distributed File System (HDFS)
  8. Spring Object XML Mapping (OXM) JAXB Example

Sunday, February 2, 2020

Python Exception Handling Tutorial

This Python exception handling tutorial gives an overview of Python exceptions and how to handle exceptions using Python exception handling.

Types of errors

Errors in your Python programs can be categorized into atleast two types-

  • Syntax errors
  • Exceptions

Syntax error

Syntax errors or compile time errors are the errors due to which your program fails to compile. Such errors are detected at the compile time itself, file name, line number and error description is displayed so you know where to look for the error and how to correct it.

For example if you don’t write colon after if statement-

def check_equality(str1, str2):
  if str1 > str2
    print(str1, 'is greater than', str2)

Then you get the compile time error as shown here-

Output

  File "F:/NETJS/NetJS_2017/Python/Test/Test.py", line 2
    if str1 > str2
                 ^
SyntaxError: invalid syntax

Exceptions

Even if a statement or expression is syntactically correct it may result in an error at run time. Errors detected during runtime are called exceptions and they disrupt the normal execution flow of the program.

For example in the following program there is an attempt to divide by zero which results in ZeroDivisionError at runtime.

def divide_num(num1, num2):
  return num1/num2

divide_num(10, 0)

Output

Traceback (most recent call last):
  File "F:/NETJS/NetJS_2017/Python/Test/Test.py", line 4, in <module>
    divide_num(10, 0)
  File "F:/NETJS/NetJS_2017/Python/Test/Test.py", line 2, in divide_num
    return num1/num2
ZeroDivisionError: division by zero

When these types of runtime errors occur in Python code, an exception object is created and raised. If there is no exception handling code to handle it then the error message is displayed that shows the context where the exception happened, in the form of a stack traceback. The exception type (at least in case of built-in exception) is printed as part of the message.

Python 3 exception hierarchy

In Python all exceptions are represented as classes and derive from BaseException class. The class hierarchy for built-in exceptions in Python is as follows.

Python 3 exception hierarchy

As you can see from the Python Exception hierarchy all built-in, non-system-exiting exceptions are derived from Exception class. All user-defined exceptions should also be derived from this class.

Warning messages are typically issued in situations where it is useful to alert the user of some condition in a program, where that condition (normally) doesn’t warrant raising an exception and terminating the program.

Warning messages are typically issued in situations where it is useful to alert the user of some condition in a program. Warnings unlike exceptions are not fatal and don't terminate the program. Warning is the base class for warning categories.

Python exception handling

While writing robust code we should provide checks for the eventuality where program may fail at run time because of some condition like zero division, file not found, type error.

Default behavior for handling such exceptions in Python is for the interpreter to print the full stack traceback, that includes the exception type (at least in case of built-in exception) and error message, and then terminate the program.

By providing your own exception handling you can display an appropriate message and then continue with the program rather than terminating the program.

To handle exception in Python you can use the following procedure-

  1. Use try block to enclose code that might throw an exception.
  2. Use except block to handle the raised exceptions.
  3. Use finally clause to perform clean up like closing the opened file.

Together these three keywords constitute the Python exception handling. General form of exception handling in Python is as follows.

try: 
 try suite
               
except Exception1:
 handler suite
except Exception2:
 handler suite
else:
 else suite
finally: 
 finally suite

There can be more than one except block, based on the type of the exception raised appropriate except block is executed. Read more in this post- Python Exception Handling - try,except,finally

If no exception is raised then the statements in the else block are executed.

Statements inside the finally block are always executed whether an exception is raised or not.

Python exception handling example

def divide_num(num1, num2):
  try:
    print('Result-',num1/num2)
  except ZeroDivisionError:
    print('Division by zero')
    print('Zero is not a valid argument here')
  else:
    print('in else block')

divide_num(10, 0)
divide_num(10, 2)

Output

Division by zero
Zero is not a valid argument here
Result- 5.0
in else block

As you can see in the first call to function 0 is passed as divisor which results in ‘ZeroDivisionError’ so the except block handles that exception. Since the exception handling is done so the program doesn’t terminate and the second function is also executed. This time there is no error so an optional else block is executed.

Apart from try, except and finally other keywords used in Python exception handling are-

  • raise- Allows you to force a specified exception to occur.
  • assert- The assert statement enables you to verify if a certain condition is true or not. If it not true then it raises AssertionError.

Python built-in exceptions

Python language has several built-in exceptions, some of the important one are listed below.

Exception Class Description
ArithmeticError The base class for those built-in exceptions that are raised for various arithmetic errors: OverflowError, ZeroDivisionError, FloatingPointError.
AssertionError Raised when an assert statement fails.
EOFError Raised when the input() function hits an end-of-file condition (EOF) without reading any data.
ImportError Raised when the import statement has troubles trying to load a module.
IndexError Raised when a sequence subscript is out of range.
KeyError Raised when a mapping (dictionary) key is not found in the set of existing keys.
OverflowError Raised when the result of an arithmetic operation is too large to be represented.
RuntimeError Raised when an error is detected that doesn’t fall in any of the other categories.
SyntaxError Raised when the parser encounters a syntax error.
IndentationError Base class for syntax errors related to incorrect indentation. This is a subclass of SyntaxError.
SystemError Raised when the interpreter finds an internal error, but the situation does not look so serious to cause it to abandon all hope.
TypeError Raised when an operation or function is applied to an object of inappropriate type.
ZeroDivisionError Raised when the second argument of a division or modulo operation is zero.
FileNotFoundError Raised when a file or directory is requested but doesn’t exist.

That's all for this topic Python Exception Handling Tutorial. If you have any doubt or any suggestions to make please drop a comment. Thanks!

>>>Return to Python Tutorial Page


Related Topics

  1. User-defined Exceptions in Python
  2. self in Python
  3. Python return Statement With Examples
  4. Constructor in Python - __init__() function
  5. Nonlocal Keyword in Python With Examples

You may also like-

  1. Changing String Case in Python
  2. Class And Object in Python
  3. Python Generator, Generator Expression, Yield Statement
  4. Convert String to int in Python
  5. What Are JVM, JRE And JDK in Java
  6. Java Concurrency Interview Questions And Answers
  7. ApplicationContextAware And BeanNameAware Interfaces in Spring Framework
  8. How to Handle Missing And Under Replicated Blocks in HDFS