If you write a complex python code , it is very important to handle errors and exceptions. While handling files, connecting to database systems and so on , you can be the best programmer in the world and still get errors that is not up to you. When you write a code for infrastructure, you need to raise exceptions and warnings to let other developers to use you code correctly.

In this post, i will go over errors, exceptions, warnings and related topics

Warnings

You can add warnings to your code.

Simple example

import warnings def fn(a): s=0; if a>100: warnings.warn('Long Wait...') for i in range(a): s+=i return s print("Start...") print(fn(1000)) print ("Ending...") 1 2 3 4 5 6 7 8 9 10 11 12 13 import warnings def fn ( a ) : s = 0 ; if a > 100 : warnings . warn ( 'Long Wait...' ) for i in range ( a ) : s += i return s print ( "Start..." ) print ( fn ( 1000 ) ) print ( "Ending..." )

If you run it you will see the following warning message:

# python ./demo.py Start... ./demo.py:14: UserWarning: Long Wait... warnings.warn('Long Wait...') 499500 Ending... 1 2 3 4 5 6 # python ./demo.py Start . . . . / demo . py : 14 : UserWarning : Long Wait . . . warnings . warn ( 'Long Wait...' ) 499500 Ending . . .

You can run it without the warning using one of the following methods

command line:

# python -W ignore ./demo.py Start... 499500 Ending... 1 2 3 4 # python -W ignore ./demo.py Start . . . 499500 Ending . . .

using PYTHONWARNINGS environment variable

# export PYTHONWARNINGS=ignore # python ./demo.py Start... 499500 Ending... 1 2 3 4 5 # export PYTHONWARNINGS=ignore # python ./demo.py Start . . . 499500 Ending . . .

in the code:

warnings.filterwarnings('ignore','.*') print(fn(1000)) 1 2 3 warnings . filterwarnings ( 'ignore' , '.*' ) print ( fn ( 1000 ) )

if you use one of the above methods with ‘error’ instead of ‘ignore’, you will get an error message and the program execution stops

# export PYTHONWARNINGS=error # python ./demo.py Start... Traceback (most recent call last): File "./demo.py", line 25, in <module> print(fn(1000)) File "./demo.py", line 14, in fn warnings.warn('Long Wait...') UserWarning: Long Wait... 1 2 3 4 5 6 7 8 9 # export PYTHONWARNINGS=error # python ./demo.py Start . . . Traceback ( most recent call last ) : File "./demo.py" , line 25 , in < module > print ( fn ( 1000 ) ) File "./demo.py" , line 14 , in fn warnings . warn ( 'Long Wait...' ) UserWarning : Long Wait . . .

Error Messages

Python routes its own error messages to stderr but it cannot know which of your messages are errors. You can write to stderr using print command (python 2.7) or function (python 3.6).

# python 2.7 print >> sys.stderr,"Wrong Argument..." # python 3.6 print("Wrong Argument", file=sys.stderr) 1 2 3 4 5 # python 2.7 print >> sys . stderr , "Wrong Argument..." # python 3.6 print ( "Wrong Argument" , file = sys . stderr )

The syntax is different so if you want to write version independent code use sys module:

import sys if arg1>0: sys.stderr.write("Wrong Argument...

") exit(1) 1 2 3 4 5 import sys if arg1 > 0 : sys . stderr . write ( "Wrong Argument...

" ) exit ( 1 )

Exception Handling

Sometimes you don’t know if your task completed successfully until you try. For example while accessing a web server it may be offline, so you need to send request and wait for response and after a timeout generate error. Thats why we need exceptions. Exception handling is not error handling, you will not use exception for something you can check for example if you divide x/y , check that y is not zero using if statement and not using exceptions

In Python an exception can be thrown , it is represented by an object (a class derived from the Exception). Throwing an exception transfers control and the function call stack is unwound until a handler capable of handling the Exception object is found

Simple example:

print("start") try: print("start try block") f = open("file1") print("end try block") except Exception: print("error opening file") print("end") 1 2 3 4 5 6 7 8 9 print ( "start" ) try : print ( "start try block" ) f = open ( "file1" ) print ( "end try block" ) except Exception : print ( "error opening file" ) print ( "end" )

If the file doesn’t exists you will see the following output:

start start try block error opening file end 1 2 3 4 start start try block error opening file end

Any exception in the try block transfers control to the except block. If the file exists the except block is ignored:

start start try block end try block end 1 2 3 4 start start try block end try block end

You can write multiple except block and also multiple exceptions for each block for example:

print("start") try: print("start try block") f = open("file1") print("end try block") except IOError: print("error opening file") except (OSError,NameError): print("OS/Name problem") except Exception: print("All other Exceptions") print("end") 1 2 3 4 5 6 7 8 9 10 11 12 print ( "start" ) try : print ( "start try block" ) f = open ( "file1" ) print ( "end try block" ) except IOError : print ( "error opening file" ) except ( OSError , NameError ) : print ( "OS/Name problem" ) except Exception : print ( "All other Exceptions" ) print ( "end" )

Note that the first except block that match the exception type will be executed so the order is important. If you place the last except block (except Exception) before any other exception it will catch it

Exception Object

You can use the exception object to get more details about the exception:

print("start") try: print("start try block") f = open("file1") print("end try block") except IOError as errobj: print("error opening file:",errobj) print("end") 1 2 3 4 5 6 7 8 print ( "start" ) try : print ( "start try block" ) f = open ( "file1" ) print ( "end try block" ) except IOError as errobj : print ( "error opening file:" , errobj ) print ( "end" )

Output:

start start try block error opening file: [Errno 2] No such file or directory: 'file1' end 1 2 3 4 start start try block error opening file : [ Errno 2 ] No such file or directory : 'file1' end

Else Block

You can add else block to the try – except blocks. It will run if no exception occurred.

print("start") try: print("start try block") f = open("file1") print("end try block") except IOError as errobj: print("error opening file:",errobj) else: print("No Exceptions") print("end") 1 2 3 4 5 6 7 8 9 10 11 print ( "start" ) try : print ( "start try block" ) f = open ( "file1" ) print ( "end try block" ) except IOError as errobj : print ( "error opening file:" , errobj ) else : print ( "No Exceptions" ) print ( "end" )

It is similar to add more statements at the end of the try block, the only difference is what happens if the statement in the else block generate an exception, it will transfer control to the calling function.

For Example:

def f2(): try: print("f2") f = open("file1") except Exception as e: print("Exception in f2") else: print("No Exceptions") def f1(): try: print("start try block") f2() print("end try block") except Exception: print("Exception in f1") print("start") f1(); print("end") 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 def f2 ( ) : try : print ( "f2" ) f = open ( "file1" ) except Exception as e : print ( "Exception in f2" ) else : print ( "No Exceptions" ) def f1 ( ) : try : print ( "start try block" ) f2 ( ) print ( "end try block" ) except Exception : print ( "Exception in f1" ) print ( "start" ) f1 ( ) ; print ( "end" )

If the file doesn’t exists the output is:

start start try block f2 Exception in f2 end try block end 1 2 3 4 5 6 start start try block f2 Exception in f2 end try block end

But if we move the open function to the else block:

def f2(): try: print("f2") except Exception as e: print("Exception in f2") else: print("No Exceptions") f = open("file1") def f1(): try: print("start try block") f2() print("end try block") except Exception: print("Exception in f1") print("start") f1(); print("end") 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 def f2 ( ) : try : print ( "f2" ) except Exception as e : print ( "Exception in f2" ) else : print ( "No Exceptions" ) f = open ( "file1" ) def f1 ( ) : try : print ( "start try block" ) f2 ( ) print ( "end try block" ) except Exception : print ( "Exception in f1" ) print ( "start" ) f1 ( ) ; print ( "end" )

The exception is now handled on f1:

start start try block f2 No Exceptions Exception in f1 end 1 2 3 4 5 6 start start try block f2 No Exceptions Exception in f1 end

The Finally Block

You can add a finally block which is (almost) always executed, even if an exception occurs

print("start") try: print("start try block") f = open("file1") print("end try block") except IOError as errobj: print("error opening file:",errobj) else: print("No Exceptions") finally: print("Always Executed") print("end") 1 2 3 4 5 6 7 8 9 10 11 12 print ( "start" ) try : print ( "start try block" ) f = open ( "file1" ) print ( "end try block" ) except IOError as errobj : print ( "error opening file:" , errobj ) else : print ( "No Exceptions" ) finally : print ( "Always Executed" ) print ( "end" )

Output without exception:

start start try block end try block No Exceptions Always Executed end 1 2 3 4 5 6 start start try block end try block No Exceptions Always Executed end

Output with exception

start start try block error opening file: [Errno 2] No such file or directory: 'file1' Always Executed end 1 2 3 4 5 start start try block error opening file : [ Errno 2 ] No such file or directory : 'file1' Always Executed end

The main use of the finally block is to release resources (locks, files, etc.)

You can write code with try and finally only if you handle the exception in the calling function

Raising Exceptions

You can raise exceptions in your code. It is useful if you don’t want to return normally

For example:

def f2(a,b): if a>0: raise ValueError("Error in f2") return a+b def f1(): print("start f1") s=f2(10,20) print("end f1",s) print("start") f1(); print("end") 1 2 3 4 5 6 7 8 9 10 11 12 13 def f2 ( a , b ) : if a > 0 : raise ValueError ( "Error in f2" ) return a + b def f1 ( ) : print ( "start f1" ) s = f2 ( 10 , 20 ) print ( "end f1" , s ) print ( "start" ) f1 ( ) ; print ( "end" )

On exception, the program terminated

# python3 ./demo7.py start start f1 Traceback (most recent call last): File "./demo7.py", line 18, in <module> f1(); File "./demo7.py", line 10, in f1 s=f2(10,20) File "./demo7.py", line 4, in f2 raise ValueError("Error in f2") ValueError: Error in f2 1 2 3 4 5 6 7 8 9 10 11 # python3 ./demo7.py start start f1 Traceback ( most recent call last ) : File "./demo7.py" , line 18 , in < module > f1 ( ) ; File "./demo7.py" , line 10 , in f1 s = f2 ( 10 , 20 ) File "./demo7.py" , line 4 , in f2 raise ValueError ( "Error in f2" ) ValueError : Error in f2

Writing Your Own Exception Class

To create a new type of exception derive a class from Exception class:

class CustomException(Exception): pass def fn(*arguments): if not all(arguments): raise CustomException("False argument in fn") try: fn('dev','',42) except CustomException as err: print("Oops:",err) 1 2 3 4 5 6 7 8 9 10 11 12 class CustomException ( Exception ) : pass def fn ( * arguments ) : if not all ( arguments ) : raise CustomException ( "False argument in fn" ) try : fn ( 'dev' , '' , 42 ) except CustomException as err : print ( "Oops:" , err )

You can add some magic methods to provide useful operations (__str__ for example)

Subscribe to our list