try except

I can do:

try:
    # do something that may fail
except:
    # do this if ANYTHING goes wrong

I can also do this:

try:
    # do something that may fail
except IDontLikeYouException:
    # say please
except YouAreTooShortException:
    # stand on a ladder

Raising New Exceptions

Exceptions are raised with a raise keyword.

raise Exception('This is the error message')

In [1]:
raise Exception('This is the error message')  #This will return an exception object that is raised
---------------------------------------------------------------------------
Exception                                 Traceback (most recent call last)
<ipython-input-1-594fbb4627ee> in <module>()
----> 1 raise Exception('This is the error message')  #This will return an exception object that is raised

Exception: This is the error message



Let's make an function that prints out a box like:


 **********
 *        *
 *        *
 **********

above box is 4*10 stars wide.

The function takes the symbol, width and height and then prints out a box according to it.

In [2]:
def boxPrint(symbol, width, height):
    print(symbol * width)            #string replication 

    for i in range(height - 2):
        print(symbol + (' ' * (width - 2)) + symbol)

    print(symbol * width)
In [3]:
boxPrint('+' , 15, 10)
+++++++++++++++
+             +
+             +
+             +
+             +
+             +
+             +
+             +
+             +
+++++++++++++++
In [4]:
boxPrint('O' , 15, 2)
OOOOOOOOOOOOOOO
OOOOOOOOOOOOOOO


Seems like it is working fine, but what if passing instead of one character to the symbol, I accidently passed 2 characters

In [5]:
boxPrint('**' , 15, 4)
******************************
**             **
**             **
******************************

Then this starts to mess up. The program hasn't crashed, but clearly this is a bug.
Rewriting the program to handle this scenario.

In [6]:
def boxPrint(symbol, width, height):

    if len(symbol) != 1:
        raise Exception("'Symbol' needs to be a string of length 1")

    print(symbol * width)            #string replication 

    for i in range(height - 2):
        print(symbol + (' ' * (width - 2)) + symbol)

    print(symbol * width)
In [7]:
boxPrint('**' , 5, 4)
---------------------------------------------------------------------------
Exception                                 Traceback (most recent call last)
<ipython-input-7-1df76806f4c7> in <module>()
----> 1 boxPrint('**' , 5, 4)

<ipython-input-6-c7a496477200> in boxPrint(symbol, width, height)
      2
      3     if len(symbol) != 1:
----> 4         raise Exception("'Symbol' needs to be a string of length 1")
      5
      6     print(symbol * width)            #string replication

Exception: 'Symbol' needs to be a string of length 1
In [8]:
boxPrint('*' , 1, 1)
*
*
In [9]:
def boxPrint(symbol, width, height):

    if len(symbol) != 1:
        raise Exception("'Symbol' needs to be a string of length 1")

    if (width < 2) or (height < 2):
        raise Exception("'width' and 'height' must be greater or equal to 2")

    print(symbol * width)            #string replication 

    for i in range(height - 2):
        print(symbol + (' ' * (width - 2)) + symbol)

    print(symbol * width)
In [10]:
boxPrint('*' , 1, 1)
---------------------------------------------------------------------------
Exception                                 Traceback (most recent call last)
<ipython-input-10-2a8522ba38e1> in <module>()
----> 1 boxPrint('*' , 1, 1)

<ipython-input-9-0c4e87896e60> in boxPrint(symbol, width, height)
      5
      6     if (width < 2) or (height < 2):
----> 7         raise Exception("'width' and 'height' must be greater or equal to 2")
      8
      9     print(symbol * width)            #string replication

Exception: 'width' and 'height' must be greater or equal to 2



The entire error message is called a 'Traceback'. It has information about the line that raised the exception.

traceback.format_exc()

The text as a string value can be obtained by traceback.format_exc() function.

In [11]:
import traceback
In [12]:
try:
    raise Exception('ErrorMessage')
except:
    errorFile = open('F:\\pythoncodes\\error_log.txt', 'a')    #opening file in append mode
    errorFile.write(traceback.format_exc())
    errorFile.close()
    print('The traceback info was written to error_log.txt')
The traceback info was written to error_log.txt
In [13]:
file = open('F:\\pythoncodes\\error_log.txt')
content = file.read()
print(content)
file.close()
Traceback (most recent call last):
  File "<ipython-input-12-0d1f867dd25d>", line 2, in <module>
    raise Exception('ErrorMessage')
Exception: ErrorMessage

Assertions and the assert Statement

An Assertion is a sanity check that makes sure the code isn't doing something obviously wrong. These checks are performed by assert statements. If they fail, an AssertionError Exception is raised.

assert condition, 'Assert Message'

Assert statements raises assertion error when the condition is false

In [14]:
assert False, 'This is the error message'
---------------------------------------------------------------------------
AssertionError                            Traceback (most recent call last)
<ipython-input-14-92fe30b0e4fb> in <module>()
----> 1 assert False, 'This is the error message'

AssertionError: This is the error message

Taking an example with a simple traffic simulator program.

In [15]:
market_2nd = {'ns' : 'green', 'ew' : 'red'}

def SwitchLights(intersection):
    for key in intersection.keys():
        if intersection[key] == 'green':
            intersection[key] = 'yellow'
        elif intersection[key] == 'yellow':
            intersection[key] = 'red'
        elif intersection[key] == 'red':
            intersection[key] = 'green'

SwitchLights(market_2nd)

But we quickly realised that our virtual cars crashing into each other.
Why did it happen?

In [16]:
market_2nd = {'ns' : 'green', 'ew' : 'red'}

def SwitchLights(intersection):
    for key in intersection.keys():
        if intersection[key] == 'green':
            intersection[key] = 'yellow'
        elif intersection[key] == 'yellow':
            intersection[key] = 'red'
        elif intersection[key] == 'red':
            intersection[key] = 'green'
print(market_2nd)
SwitchLights(market_2nd)
print(market_2nd)
{'ns': 'green', 'ew': 'red'}
{'ns': 'yellow', 'ew': 'green'}

In second case the traffic is going in both north-south and east-west direction!

Making an assert statement to overcome this dangerous bug

In [17]:
market_2nd = {'ns' : 'green', 'ew' : 'red'}

def SwitchLights(intersection):
    for key in intersection.keys():
        if intersection[key] == 'green':
            intersection[key] = 'yellow'
        elif intersection[key] == 'yellow':
            intersection[key] = 'red'
        elif intersection[key] == 'red':
            intersection[key] = 'green'

        assert 'red' in intersection.values(), 'Neither light is red!' + str(intersection)
print(market_2nd)
SwitchLights(market_2nd)
print(market_2nd)
{'ns': 'green', 'ew': 'red'}
---------------------------------------------------------------------------
AssertionError                            Traceback (most recent call last)
<ipython-input-17-dc265965f131> in <module>()
     12         assert 'red' in intersection.values(), 'Neither light is red!' + str(intersection)
     13 print(market_2nd)
---> 14 SwitchLights(market_2nd)
     15 print(market_2nd)

<ipython-input-17-dc265965f131> in SwitchLights(intersection)
     10             intersection[key] = 'green'
     11
---> 12         assert 'red' in intersection.values(), 'Neither light is red!' + str(intersection)
     13 print(market_2nd)
     14 SwitchLights(market_2nd)

AssertionError: Neither light is red!{'ns': 'yellow', 'ew': 'green'}

You shouldn't do an except with assert. If the assert fails, your program crashes.

This will reduce the amount of code check to find out the bugs. Assert are for programmer errors, not a user errors



-You can raise your own exceptions: raise Exception('This is the error message')

-You can also use assertions which runs if the condition is false: assert condition, 'Error Message'

-Assertions are for detecting programmer errors that are not meant to be recovered from. User errors should raise exceptions