4
\$\begingroup\$

I am trying to learn how to effectively use error handling in my code. To do this, I have created a class inside main.py which reads the value of a specified curve at a specified date.

I then have my file data_reader.py, which reads in the specified curve (into a Pandas dataframe) from a CSV file. The index of this curve is a date.

Finally, I have my error handling file, error_handler.py.

main.py

from data_reader import read_curve
from datetime import datetime, timedelta
import sys
from error_handler import CustomException, CurveValueNotFoundError


def get_curve_value(curve_name, lookup_date):

    lookup_date = datetime.strptime(lookup_date, '%d/%m/%Y')

    curve_value = None
    tries_remaining = 5

    while curve_value is None:
        try:
            curve_value = read_curve(curve_name, lookup_date, tries_remaining)
            return curve_value

        except CurveValueNotFoundError as e:
            e.return_to_user()
            tries_remaining -= 1
            lookup_date -= timedelta(days=1)

        except CustomException as e:
            e.return_to_user()
            if e.fatal:
                sys.exit(1)


if __name__ == '__main__':
    print('Curve value: {}'.format(get_curve_value('RPI2019', '30/06/2019')))

data_reader.py

import pandas as pd
import pathlib
import error_handler


def read_curve(curve_name, lookup_value, tries_remaining):
    try:
        curve = pd.read_csv('{}/curves/{}.csv'.format(str(pathlib.Path().absolute()), curve_name), index_col='Date', parse_dates=True)
        val = float(curve.loc[lookup_value])
        return val
    except pd.errors.EmptyDataError as e:
        raise error_handler.NoCurveValuesError(curve_name, __name__, fatal=True)
    except FileNotFoundError:
        raise error_handler.CurveNotFoundError(curve_name, __name__, fatal=True)
    except KeyError:
        raise error_handler.CurveValueNotFoundError(curve_name, lookup_value, tries_remaining, __name__)
    except Exception as e:
        raise error_handler.CustomException(e, __name__, fatal=True)

error_handler.py

class CustomException(Exception):
    def __init__(self, message, raised_from, fatal):
        self.message = message
        self.raised_from = raised_from
        self.fatal = fatal

    def return_to_user(self):
        print("The following error occurred in the module {}.py: {}".format(self.raised_from, self.message))

class CurveNotFoundError(CustomException):
    def __init__(self, curve_name, raised_from, fatal=True):
        message = "The curve {} could not be found.".format(curve_name)
        CustomException.__init__(self, message, raised_from, fatal)

class NoCurveValuesError(CustomException):
    def __init__(self, curve_name, raised_from, fatal=True):
        message = "The curve {} was successfully loaded but contains no data.".format(curve_name)
        CustomException.__init__(self, message, raised_from, fatal)

class CurveValueNotFoundError(CustomException):
    def __init__(self, curve_name, lookup_value, tries_remaining, raised_from, fatal=False):
        message = "The curve {} is not defined for the lookup '{}'. Tries remaining: {}.".format(curve_name, lookup_value, tries_remaining)
        CustomException.__init__(self, message, raised_from, fatal)
        if tries_remaining == 0:
            raise CustomException("Too many missing values", __name__, fatal=True)

Errors that should terminate execution include:

  • If the CSV file containing the user-specified curve cannot be found

  • If the CSV file for the curve is empty

  • If, after 5 tries (changing the lookup date by -1 days per try), no curve values can be found

Is my approach towards error handling (including my handling of fatal / non-fatal errors) a good approach? How can I improve this?

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.