Home > Software engineering >  Raise exception as e in if statement
Raise exception as e in if statement

Time:06-23

I have come up with some code to send a file's exceptions as an email, and update a .txt log file. This method works for the following example:

from send_mail import send_error_email
from datetime import datetime
import logging

logging.basicConfig(filename='log.txt', level=logging.DEBUG, format='%(asctime)s %(levelname)s %(name)s %(message)s')
logger=logging.getLogger(__name__)

now = datetime.now()
date = now.strftime("%m/%d/%Y")
time = now.strftime("%H:%M:%S")

try:
    a = 2   'seven'
except Exception as e:
    print(e)
    send_error_email(exception=e, message="Can't add string and int")
    logging.exception('Oh no! Error on {} at {} Here is the traceback info:'.format(date, time))

However, the functions I want to apply it to have a lot of if/else syntax where exceptions are raised in the if or else block. Here are two examples:

def is_empty(test_df):
    if(test_df.empty):
        raise Exception("The sheet: {} is empty".format(sheet_name))
    else:
        pass
    for col in test_df.columns:
        miss = test_df[col].isnull().sum()
        if miss>0:
            raise Exception("{} has {} missing value(s)".format(col,miss))
    return None

or

def column_validation(sheet_name, input_file, expected_columns, input_columns, months):
    if len(expected_columns) == len(input_columns):
        for i in range(len(input_columns)):
            if input_columns[i] != expected_columns[i]:
                if sheet_name == "G2 30yr":
                    if input_columns[i][:3] in months:
                        continue
                elif sheet_name != "G2 30yr":
                    if input_columns[i] in months:
                        continue
                else:
                    raise Exception("The {} sheet of file: {}'s columns are not in expected format.".format(sheet_name, input_file))
    else:
        raise Exception("Number of columns in file: {}, {} sheet are not as expected".format(input_file, sheet_name))
    return None

I'm not sure how to employ the emailing and log function with exceptions that are raised outside of try/except blocks where I can access the Exception attributes using except Exception as e:. The below else will send the email notification but will not correctly update the log file.

else:
    send_error_email(exception=e, message="Can't add string and int")
    logging.error('Oh no! Error on {} at {} Here is the traceback info:'.format(date, time), stack_info = True)

CodePudding user response:

def catch_exception_and_send_email(func):
    def exception_catcher(*args, **kwargs):
        try:
            return func(*args, **kwargs)
        except Exception e:
            print(e)
            now = datetime.now()
            date = now.strftime("%m/%d/%Y")
            time = now.strftime("%H:%M:%S")
            send_error_email(exception=e, message="Can't add string and int")
            logging.exception('Oh no! Error on {} at {} Here is the traceback info:'.format(date, time))
    return exception_catcher

Now, use this to decorate the functions you anticipate possibly raising exceptions:

@exception_catcher
def is_empty(test_df):
    # function body


@exception_catcher
def column_validation(sheet_name, input_file, expected_columns, input_columns, months):
    # function body

Now, whenever any of your decorated functions are called, the decorator's code will run, first trying your function's code, and if your function raises an exception, the decorator catches it, logs it, and sends the email.

I'd also suggest implementing custom exceptions, but that's beside the point here.

  • Related