Javascript required
Skip to content Skip to sidebar Skip to footer

If Error Ignore and Continue Python

30. Errors and Exception Handling

By Bernd Klein. Last modified: 29 Jun 2022.

Exception Handling

An exception is an error that happens during the execution of a program. Exceptions are known to non-programmers as instances that do not conform to a general rule. The name "exception" in computer science has this meaning as well: It implies that the problem (the exception) doesn't occur frequently, i.e. the exception is the "exception to the rule". Exception handling is a construct in some programming languages to handle or deal with errors automatically. Many programming languages like C++, Objective-C, PHP, Java, Ruby, Python, and many others have built-in support for exception handling.

Error handling is generally resolved by saving the state of execution at the moment the error occurred and interrupting the normal flow of the program to execute a special function or piece of code, which is known as the exception handler. Depending on the kind of error ("division by zero", "file open error" and so on) which had occurred, the error handler can "fix" the problem and the programm can be continued afterwards with the previously saved data.

Python logo with band aid

Exception Handling in Python

Exception handling in Python is very similar to Java. The code, which harbours the risk of an exception, is embedded in a try block. While in Java exceptions are caught by catch clauses, in Python we have statements introduced by an "except" keyword. It's possible to create "custom-made" exceptions: With the raise statement it's possible to force a specified exception to occur.

Let's look at a simple example. Assuming we want to ask the user to enter an integer number. If we use a input(), the input will be a string, which we have to cast into an integer. If the input isn't a valid integer, we will generate (raise) a ValueError. We show this in the following interactive session:

            n            =            int            (            input            (            "Please enter a number: "            ))          

With the aid of exception handling, we can write robust code for reading an integer from input:

            while            True            :            try            :            n            =            input            (            "Please enter an integer: "            )            n            =            int            (            n            )            break            except            ValueError            :            print            (            "No valid integer! Please try again ..."            )            print            (            "Great, you successfully entered an integer!"            )          

It's a loop, which breaks only if a valid integer has been given. The while loop is entered. The code within the try clause will be executed statement by statement. If no exception occurs during the execution, the execution will reach the break statement and the while loop will be left. If an exception occurs, i.e. in the casting of n, the rest of the try block will be skipped and the except clause will be executed. The raised error, in our case a ValueError, has to match one of the names after except. In our example only one, i.e. "ValueError:". After having printed the text of the print statement, the execution does another loop. It starts with a new input().

We could turn the code above into a function, which can be used to have a foolproof input.

            def            int_input            (            prompt            ):            while            True            :            try            :            age            =            int            (            input            (            prompt            ))            return            age            except            ValueError            as            e            :            print            (            "Not a proper integer! Try it again"            )          

We use this with our dog age example from the chapter Conditional Statements.

            def            dog2human_age            (            dog_age            ):            human_age            =            -            1            if            dog_age            <            0            :            human_age            =            -            1            elif            dog_age            ==            0            :            human_age            =            0            elif            dog_age            ==            1            :            human_age            =            14            elif            dog_age            ==            2            :            human_age            =            22            else            :            human_age            =            22            +            (            dog_age            -            2            )            *            5            return            human_age          
              age              =              int_input              (              "Age of your dog? "              )              print              (              "Age of the dog: "              ,              dog2human_age              (              age              ))            

OUTPUT:

Not a proper integer! Try it again Not a proper integer! Try it again Age of the dog:  37            

Multiple Except Clauses

A try statement may have more than one except clause for different exceptions. But at most one except clause will be executed.

Our next example shows a try clause, in which we open a file for reading, read a line from this file and convert this line into an integer. There are at least two possible exceptions:

          an IOError ValueError                  

Just in case we have an additional unnamed except clause for an unexpected error:

              import              sys              try              :              f              =              open              (              'integers.txt'              )              s              =              f              .              readline              ()              i              =              int              (              s              .              strip              ())              except              IOError              as              e              :              errno              ,              strerror              =              e              .              args              print              (              "I/O error(              {0}              ):                            {1}              "              .              format              (              errno              ,              strerror              ))              # e can be printed directly without using .args:              # print(e)              except              ValueError              :              print              (              "No valid integer in line."              )              except              :              print              (              "Unexpected error:"              ,              sys              .              exc_info              ()[              0              ])              raise            

OUTPUT:

I/O error(2): No such file or directory            

The handling of the IOError in the previous example is of special interest. The except clause for the IOError specifies a variable "e" after the exception name (IOError). The variable "e" is bound to an exception instance with the arguments stored in instance.args. If we call the above script with a non-existing file, we get the message:

I/O error(2): No such file or directory

And if the file integers.txt is not readable, e.g. if we don't have the permission to read it, we get the following message:

I/O error(13): Permission denied

An except clause may name more than one exception in a tuple of error names, as we see in the following example:

              try              :              f              =              open              (              'integers.txt'              )              s              =              f              .              readline              ()              i              =              int              (              s              .              strip              ())              except              (              IOError              ,              ValueError              ):              print              (              "An I/O error or a ValueError occurred"              )              except              :              print              (              "An unexpected error occurred"              )              raise            

OUTPUT:

An I/O error or a ValueError occurred            

We want to demonstrate now, what happens, if we call a function within a try block and if an exception occurs inside the function call:

              def              f              ():              x              =              int              (              "four"              )              try              :              f              ()              except              ValueError              as              e              :              print              (              "got it :-) "              ,              e              )              print              (              "Let's get on"              )            

OUTPUT:

got it :-)  invalid literal for int() with base 10: 'four' Let's get on            

the function catches the exception.

We will extend our example now so that the function will catch the exception directly:

              def              f              ():              try              :              x              =              int              (              "four"              )              except              ValueError              as              e              :              print              (              "got it in the function :-) "              ,              e              )              try              :              f              ()              except              ValueError              as              e              :              print              (              "got it :-) "              ,              e              )              print              (              "Let's get on"              )            

OUTPUT:

got it in the function :-)  invalid literal for int() with base 10: 'four' Let's get on            

As we have expected, the exception is caught inside the function and not in the callers exception:

We add now a "raise", which generates the ValueError again, so that the exception will be propagated to the caller:

              def              f              ():              try              :              x              =              int              (              "four"              )              except              ValueError              as              e              :              print              (              "got it in the function :-) "              ,              e              )              raise              try              :              f              ()              except              ValueError              as              e              :              print              (              "got it :-) "              ,              e              )              print              (              "Let's get on"              )            

OUTPUT:

got it in the function :-)  invalid literal for int() with base 10: 'four' got it :-)  invalid literal for int() with base 10: 'four' Let's get on            

Live Python training

instructor-led training course

Upcoming online Courses

Enrol here

Custom-made Exceptions

It's possible to create Exceptions yourself:

              raise              SyntaxError              (              "Sorry, my fault!"              )            

OUTPUT:

Traceback              (most recent call last):   File              "C:\\Users\\melis\\Anaconda3\\lib\\site-packages\\IPython\\core\\interactiveshell.py", line              3326, in              run_code              exec(code_obj, self.user_global_ns, self.user_ns)                              File                            "<ipython-input-15-a5649918d59e>"              , line                            1              , in                            <module>                              raise SyntaxError("Sorry, my fault!")                              File                            "<string>"              , line                            unknown              SyntaxError              :              Sorry, my fault!            

The best or the Pythonic way to do this, consists in defining an exception class which inherits from the Exception class. You will have to go through the chapter on Object Oriented Programming to fully understand the following example:

              class              MyException              (              Exception              ):              pass              raise              MyException              (              "An exception doesn't always prove the rule!"              )            

OUTPUT:

              ---------------------------------------------------------------------------              MyException              Traceback (most recent call last)              <ipython-input-3-d75bff75fe3a>              in              <module>                              2              pass                              3              ----> 4                                          raise              MyException(              "An exception doesn't always prove the rule!"              )              MyException: An exception doesn't always prove the rule!

Clean-up Actions (try ... finally)

So far the try statement had always been paired with except clauses. But there is another way to use it as well. The try statement can be followed by a finally clause. Finally clauses are called clean-up or termination clauses, because they must be executed under all circumstances, i.e. a "finally" clause is always executed regardless if an exception occurred in a try block or not. A simple example to demonstrate the finally clause:

              try              :              x              =              float              (              input              (              "Your number: "              ))              inverse              =              1.0              /              x              finally              :              print              (              "There may or may not have been an exception."              )              print              (              "The inverse: "              ,              inverse              )            

OUTPUT:

Your number: 34 There may or may not have been an exception. The inverse:  0.029411764705882353            

Combining try, except and finally

"finally" and "except" can be used together for the same try block, as it can be seen in the following Python example:

              try              :              x              =              float              (              input              (              "Your number: "              ))              inverse              =              1.0              /              x              except              ValueError              :              print              (              "You should have given either an int or a float"              )              except              ZeroDivisionError              :              print              (              "Infinity"              )              finally              :              print              (              "There may or may not have been an exception."              )            

OUTPUT:

Your number: 23 There may or may not have been an exception.            

else Clause

The try ... except statement has an optional else clause. An else block has to be positioned after all the except clauses. An else clause will be executed if the try clause doesn't raise an exception.

The following example opens a file and reads in all the lines into a list called "text":

              import              sys              file_name              =              sys              .              argv              [              1              ]              text              =              []              try              :              fh              =              open              (              file_name              ,              'r'              )              text              =              fh              .              readlines              ()              fh              .              close              ()              except              IOError              :              print              (              'cannot open'              ,              file_name              )              if              text              :              print              (              text              [              100              ])            

OUTPUT:

This example receives the file name via a command line argument. So make sure that you call it properly: Let's assume that you saved this program as "exception_test.py". In this case, you have to call it with

          python exception_test.py integers.txt        

If you don't want this behaviour, just change the line "file_name = sys.argv[1]" to "file_name = 'integers.txt'".

The previous example is nearly the same as:

              import              sys              file_name              =              sys              .              argv              [              1              ]              text              =              []              try              :              fh              =              open              (              file_name              ,              'r'              )              except              IOError              :              print              (              'cannot open'              ,              file_name              )              else              :              text              =              fh              .              readlines              ()              fh              .              close              ()              if              text              :              print              (              text              [              100              ])            

OUTPUT:

The main difference is that in the first case, all statements of the try block can lead to the same error message "cannot open ...", which is wrong, if fh.close() or fh.readlines() raise an error.

Live Python training

instructor-led training course

Upcoming online Courses

Enrol here

jullheeut1938.blogspot.com

Source: https://python-course.eu/python-tutorial/errors-and-exception-handling.php