Q3

In this question, you'll be doing some error handling. There's only one function to finish coding below--the logger function--but there's a LOT of other code that's already written for you! This will start introducing you to working with existing codebases.

A

In this question, you'll write a logger. This is a critical component of any full-scale application: when something goes wrong, and you start the debugging process, it helps immensely to have logs of activity of your application to see where it started going off the rails.

The log will take the form of a dictionary. The keys of the dictionary will be the name of the method called, and the value will be the integer code of the method's output. OR, in the case of an exception, the integer code of the exception. You can access this code in the except block:

try:
    some_code
except Exception as e:
    e.value

You'll need to save this e.value in your log dictionary for the output of the function call.

Call all three of the functions below:

  • unreliable1
  • unreliable2
  • unreliable3

and record their outputs in the dictionary.

In summary, these are your goals:

  1. In logger(), call each of the three methods once: unreliable1(), unreliable2(), unreliable3()
  2. When calling each method, wrap them in try / except blocks so no exceptions escape to crash the program.
  3. If an exception occurs, record its value to the dictionary for that function.
  4. If NO exception occurs, and the function completes, it will return a value. Record that value in the dictionary for that function.

In [ ]:
"""
The below classes--Error1, Error2, and Error3--are the names of the possible
errors that can be raised, and which you'll have to protect against.
"""
import random
class Error1(Exception):
    def __init__(self, value):
        self.value = value
    def __str__(self):
        return repr(self.value)

class Error2(Exception):
    def __init__(self, value):
        self.value = value
    def __str__(self):
        return repr(self.value)

class Error3(Exception):
    def __init__(self, value):
        self.value = value
    def __str__(self):
        return repr(self.value)
    
"""
The following three functions do SUPER IMPORTANT THINGS!
However, they are very prone to throwing exceptions, so when
you call them, you'll need to properly protect the calls!
"""
    
def unreliable1():
    for i in range(1, 4):
        if random.randint(0, 1) == 1:
            raise Error1(i)
    return random.randint(10, 1000000)

def unreliable2():
    for i in range(4, 7):
        if random.randint(0, 1) == 1:
            raise Error2(i)
    return random.randint(10, 1000000)

def unreliable3():
    for i in range(7, 10):
        if random.randint(0, 1) == 1:
            raise Error3(i)
    return random.randint(10, 1000000)

###
# Finish this method!
###

def logger():
    logs = {
        'unreliable1': 0,
        'unreliable2': 0,
        'unreliable3': 0,
    }
    
    ### BEGIN SOLUTION
    
    ### END SOLUTION
    
    return logs

In [ ]:
random.seed(10)
logs = logger()
assert logs['unreliable1'] == 2
assert logs['unreliable2'] == 4
assert logs['unreliable3'] == 9

In [ ]:
random.seed(381734)
logs = logger()
assert logs['unreliable1'] == 1
assert logs['unreliable2'] == 5
assert logs['unreliable3'] == 7

In [ ]:
random.seed(895572877675748)
logs = logger()
assert logs['unreliable1'] == 1
assert logs['unreliable2'] == 297436
assert logs['unreliable3'] == 8