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...")
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...
You can run it without the warning using one of the following methods
command line:
# python -W ignore ./demo.py Start... 499500 Ending...
using PYTHONWARNINGS environment variable
# export PYTHONWARNINGS=ignore # python ./demo.py Start... 499500 Ending...
in the code:
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...
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)
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...\n") 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")
If the file doesn’t exists you will see the following output:
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
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")
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")
Output:
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")
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")
If the file doesn’t exists the output is:
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")
The exception is now handled on f1:
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")
Output without exception:
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
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")
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
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)
You can add some magic methods to provide useful operations (__str__ for example)
Subscribe to our list