15.2. Exception Raise

  • Used when error occurs

  • You can catch exception and handles erroneous situation

  • If file does not exists

  • If no permissions to read file

  • If function argument is invalid type (ie. int('one'))

  • If value is incorrect (ie. negative Kelvin temperature)

  • If network or database connection could not be established

15.2.1. Raising Exceptions

  • Exceptions can have message

  • You choose which exception best represent error

Raise Exception without message:

>>> raise RuntimeError
Traceback (most recent call last):
RuntimeError

Exception with additional message:

>>> raise RuntimeError('Some message')
Traceback (most recent call last):
RuntimeError: Some message

15.2.2. Example

We want to check if Kelvin temperature given by user is not negative. Note that Kelvin temperatures below zero doesn't exist, hence it's an absolute scale. In order to do so, we need to ask user to input value. Let's assume user input -1.

>>> temperature = -1  # User input this value

Now we need to check if the temperature is not negative. If temperature is 0 or above we can proceed with program execution. However if the temperature is below zero... Then we should warn user about problem and exit the program. This is why we have exceptions. We can break execution of a program in erroneous situations.

>>> if temperature > 0.0:
...     print('Temperature is valid')
... else:
...     raise ValueError('Kelvin cannot be negative')
Traceback (most recent call last):
ValueError: Kelvin cannot be negative

Good software communicates well with programmer. Exceptions are common language to talk about problems and not-nominal (abnormal) situations in your code.

>>> def check(temperature):
...     if type(temperature) not in {float, int}:
...         raise TypeError('Temperature must be int or float')
...     if temperature < 0:
...         raise ValueError('Kelvin temperature cannot be negative')
...     return temperature

15.2.3. Use Case - 0x01

>>> def apollo13():
...     raise RuntimeError('Oxygen tank explosion')
>>>
>>>
>>> apollo13()
Traceback (most recent call last):
RuntimeError: Oxygen tank explosion
>>> def apollo18():
...     raise NotImplementedError('Mission dropped due to budget cuts')
>>>
>>>
>>> apollo18()
Traceback (most recent call last):
NotImplementedError: Mission dropped due to budget cuts

15.2.4. Assignments

Code 15.1. Solution
"""
* Assignment: Exception Raise One
* Type: class assignment
* Complexity: easy
* Lines of code: 2 lines
* Time: 3 min

English:
    1. Validate value passed to a `result` function:
        a. If `value` is less than zero, raise `ValueError`
    2. Write solution inside `result` function
    3. Run doctests - all must succeed

Polish:
    1. Sprawdź poprawność wartości przekazanej do funckji `result`:
        a. Jeżeli `value` jest mniejsze niż zero, podnieś wyjątek `ValueError`
    2. Rozwiązanie zapisz wewnątrz funkcji `result`
    3. Uruchom doctesty - wszystkie muszą się powieść

Hints:
    * `if`
    * `raise`

Tests:
    >>> import sys; sys.tracebacklimit = 0

    >>> result(1)
    >>> result(0)
    >>> result(-1)
    Traceback (most recent call last):
    ValueError
"""

# Validate value passed to a `result` function:
# If `value` is less than zero, raise `ValueError`
# Write solution inside `result` function
# type: Callable[[int], None]
def result(value):
    ...


Code 15.2. Solution
"""
* Assignment: Exception Raise Many
* Type: class assignment
* Complexity: easy
* Lines of code: 6 lines
* Time: 3 min

English:
    1. Validate value passed to a `result` function
    2. If `value` is:
        a. other type than `int` or `float` raise `TypeError`
        b. less than zero, raise `ValueError`
        c. below `ADULT`, raise `PermissionError`
    3. Write solution inside `result` function
    4. Run doctests - all must succeed

Polish:
    1. Sprawdź poprawność wartości przekazanej do funckji `result`
    2. Jeżeli `age` jest:
        a. innego typu niż `int` lub `float`, podnieś wyjątek `TypeError`
        b. mniejsze niż zero, podnieś wyjątek `ValueError`
        c. mniejsze niż `ADULT`, podnieś wyjątek `PermissionError`
    3. Rozwiązanie zapisz wewnątrz funkcji `result`
    4. Uruchom doctesty - wszystkie muszą się powieść

Hints:
    * `not in`
    * `raise`
    * `if`
    * `isinstance()`
    * `type()`

Tests:
    >>> import sys; sys.tracebacklimit = 0

    >>> result(18)
    >>> result(17.9999)
    Traceback (most recent call last):
    PermissionError
    >>> result(-1)
    Traceback (most recent call last):
    ValueError
    >>> result('one')
    Traceback (most recent call last):
    TypeError
    >>> result(True)
    Traceback (most recent call last):
    TypeError
"""

ADULT = 18

# Validate value passed to a `result` function
# If `value` is:
#  a. other type than `int` or `float` raise `TypeError`
#  b. less than zero, raise `ValueError`
#  c. below `ADULT`, raise `PermissionError`
# Write solution inside `result` function
# type: Callable[[int|float], None]
def result(age):
    ...


Code 15.3. Solution
"""
* Assignment: Exception Raise PermissionError
* Type: class assignment
* Complexity: easy
* Lines of code: 4 lines
* Time: 3 min

English:
    1. Check username and password passed to a `login` function
    2. If `username` is 'mwatney' and `password` is 'myVoiceIsMyPassword'
       then print 'logged in'
    3. If any value is other than mentioned, raise an exception
       PermissionError with message 'Invalid username and/or password'
    4. Non-functional requirements:
        a. Write solution inside `result` function
        b. Mind the indentation level
    5. Run doctests - all must succeed

Polish:
    1. Sprawdź username i password przekazane do funckji `login`
    2. Jeżeli username jest 'mwatney' i hasło jest 'myVoiceIsMyPassword'
       to wyświetl na ekranie napis 'logged in'
    3. Jeżeli którakolwiek wartość jest inna, to podnieś wyjątek
       PermissionError z komunikatem 'Invalid username and/or password'
    4. Wymagania niefunkcjonalne:
        a. Rozwiązanie zapisz wewnątrz funkcji `result`
        b. Zwróć uwagę na poziom wcięć
    5. Uruchom doctesty - wszystkie muszą się powieść

Hints:
    * `not in`
    * `raise`
    * `if`

Tests:
    >>> import sys; sys.tracebacklimit = 0

    >>> login('mwatney', 'myVoiceIsMyPassword')
    logged in
    >>> login('badusername', 'myVoiceIsMyPassword')
    Traceback (most recent call last):
    PermissionError: Invalid username and/or password
    >>> login('mwatney', 'badpassword')
    Traceback (most recent call last):
    PermissionError: Invalid username and/or password
    >>> login('admin', 'admin')
    Traceback (most recent call last):
    PermissionError: Invalid username and/or password
"""

# Username must be 'mwatney'
# Password must be 'myVoiceIsMyPassword'
# type: Callable[[str,str], Exception|None]
def login(username, password):
    ...