Back to the topic

The mark scheme starts on a new page, so you can print pages one and two for a student and keep the last page yourself. Everything prints in black on white whichever theme you are using.

Python · Advanced 5

Exceptions, Logging and Defensive Code

Section A: 10 multiple choice questions, 10 marks. Section B: 5 written questions, 22 marks. Total 32 marks.

Name

Class

Date

Mark  / 32

Section A

Circle the letter of the correct answer. One mark each.

  1. 1When does the else block of a try statement run?1
    1. AWhen an exception was raised
    2. BOnly when there is a finally block
    3. CAlways
    4. DWhen no exception was raised in the try block
  2. 2When does a finally block run?1
    1. AOnly if there was an error
    2. BAlways, whether or not an exception occurred
    3. COnly when the program ends
    4. DOnly if there was no error
  3. 3Why should except KeyError be placed before except LookupError?1
    1. APython uses the first matching handler, and KeyError is a kind of LookupError
    2. BKeyError is faster
    3. CIt makes no difference
    4. DLookupError cannot be caught
  4. 4What does raise ValueError('bad') from original do?1
    1. ALogs the error to a file
    2. BRaises the original error again
    3. CRaises a new exception while keeping the original as its cause
    4. DIgnores the original error
  5. 5Why create a custom exception class, such as InsufficientFunds?1
    1. APython requires it
    2. BIt names the problem in the program's own terms and can carry data
    3. CIt runs faster than a built-in one
    4. DIt stops the error being raised
  6. 6Which is the correct use of an assertion?1
    1. AChecking that the user typed a valid age
    2. BChecking that a network connection works
    3. CChecking that a file exists
    4. DChecking something that should never be false unless the code has a bug
  7. 7What does 'fail fast' mean?1
    1. AStop at the first sign of a problem instead of carrying on with bad data
    2. BRestart the program after every error
    3. CIgnore errors to save time
    4. DMake the program run quickly
  8. 8Which logging level is for something unexpected where the program can carry on?1
    1. ADEBUG
    2. BCRITICAL
    3. CWARNING
    4. DINFO
  9. 9In which direction should a Python traceback be read to find the error first?1
    1. AFrom the first line downwards
    2. BIt cannot be read
    3. CFrom the last line upwards
    4. DFrom the middle
  10. 10Why is logging usually better than print for recording what a program does?1
    1. ALevels and handlers let you control what is recorded and where, without changing the code
    2. BPrint cannot show numbers
    3. CPrint is not allowed in a program
    4. DLogging is faster than print

Section B

Answer in the space provided. The number of marks tells you how many separate points to make.

  1. 1DescribeDescribe the purpose of the try, except, else and finally parts of a Python try statement.4
  2. 2StateThe subprogram divide is called three times, as shown. State the output of the program.4
    Python
    def divide(a, b):
        try:
            result = a / b
        except ZeroDivisionError:
            print("cannot divide by zero")
            return None
        except TypeError as problem:
            print("bad types:", problem)
            return None
        else:
            print("division worked")
            return result
        finally:
            print("done with", repr(a), repr(b))
    
    print(divide(10, 2))
    print(divide(1, 0))
    print(divide("a", 2))
  3. 3ExplainExplain the difference between an exception and an assertion, and state when each should be used.4
  4. 4WriteWrite a custom exception class called InvalidAgeError, and a subprogram check_age that takes an age and raises an InvalidAgeError with a suitable message if the age is less than 0 or greater than 130. Otherwise the subprogram should return the age.4
  5. 5DiscussA programmer records what a program is doing using print statements. Discuss whether the programmer should use the logging module instead.6

Mark scheme

Section A

1D2B3A4C5B6D7A8C9C10A

Section B

1 Describe the purpose of the try, except, else and finally parts of a Python try statement. 4

One mark for each of the following, to a maximum of 4.

  • try contains the code that might cause an error (raise an exception)
  • except contains the code that handles a particular error if one occurs
  • else runs only if no exception occurred in the try block
  • finally always runs, whether or not an exception occurred, and is used for clean-up

Model answer. The try block contains the code that might cause an error. The except block contains the code that handles a particular error if one occurs. The else block runs only if no exception occurred in the try block. The finally block always runs, whether or not an exception occurred, and is used for clean-up such as closing a file.

2 The subprogram divide is called three times, as shown. State the output of the program. 4

One mark for each of the following, to a maximum of 4.

  • The first call outputs division worked, then done with 10 2, then 5.0
  • The second call outputs cannot divide by zero, then done with 1 0, then None
  • The finally block runs in each case, after the try or except code but before the value is returned
  • The third call outputs bad types, with the message about the operand types, then done with 'a' 2 and None

Model answer. For divide(10, 2) the output is division worked, then done with 10 2, and then 5.0 is printed. For divide(1, 0) the output is cannot divide by zero, then done with 1 0, and then None is printed. For divide('a', 2) the output is bad types: unsupported operand type(s) for /: 'str' and 'int', then done with 'a' 2, and then None is printed. The finally block runs in every case, after the try or except code and just before the value is returned.

3 Explain the difference between an exception and an assertion, and state when each should be used. 4

One mark for each of the following, to a maximum of 4.

  • An exception is raised when something goes wrong while the program is running, such as invalid input or a missing file
  • Exceptions should be used for problems that can occur even when the program is correct, and can be handled with try and except
  • An assertion checks that a condition that should always be true is true, and stops the program if it is not
  • Assertions are for finding programmer mistakes and can be switched off, so must not be used to validate input

Model answer. An exception is raised when something goes wrong while the program is running, such as invalid input or a missing file, and it can be caught and handled using try and except. Exceptions should be used for problems that can happen even when the program is correct. An assertion checks that a condition that should always be true really is, and stops the program if it is not. Assertions are for finding mistakes made by the programmer, and because they can be switched off they must not be used to validate input.

4 Write a custom exception class called InvalidAgeError, and a subprogram check_age that takes an age and raises an InvalidAgeError with a suitable message if the age is less than 0 or greater than 130. Otherwise the subprogram should return the age. 4

One mark for each of the following, to a maximum of 4.

  • A class InvalidAgeError that inherits from Exception
  • A subprogram check_age with a parameter
  • Tests whether the age is less than 0 or greater than 130
  • Raises InvalidAgeError with a message, otherwise returns the age

Model answer.

Python
class InvalidAgeError(Exception):
    pass

def check_age(age):
    if age < 0 or age > 130:
        raise InvalidAgeError("age must be between 0 and 130, not " + str(age))
    return age

print(check_age(15))
try:
    check_age(200)
except InvalidAgeError as problem:
    print(problem)

The new class inherits from Exception. check_age tests whether the age is less than 0 or greater than 130 and raises the new exception with a message if so, and otherwise returns the age.

5 A programmer records what a program is doing using print statements. Discuss whether the programmer should use the logging module instead. 6

One mark for each of the following, to a maximum of 6.

  • Logging messages have levels (debug, info, warning, error), so the amount of detail can be changed without editing the code
  • Print statements have to be found and removed or commented out when they are no longer wanted
  • Logging can send messages to a file or a server, so they can be reviewed after the program has run
  • Log messages can carry formatting such as the time, level and module, which helps to find the cause of a problem
  • Disadvantage: logging takes more effort to set up than a print statement, and logs can grow large or contain sensitive data
  • A reasoned conclusion: logging is better for anything beyond a small, short lived program

Model answer. The logging module gives each message a level such as debug, info, warning or error, so the programmer can change how much detail is recorded without editing the code, whereas print statements have to be found and removed when they are no longer wanted. Logging can send messages to a file or a server, so they can be reviewed after the program has run, and each message can be formatted to include the time, the level and the module, which helps in finding the cause of a problem. On the other hand it takes more effort to set up than a print statement, and log files can become large or contain sensitive data if the programmer is not careful. For anything more than a small, short lived program the programmer should therefore use logging.