Monday, October 8, 2012

Exception handling idiom for raising exceptions, and doing error tasks (logging, writing to file, etc.)


Exception handling idiom to eliminate:

1. excessive (i.e. double-logging) and logging at multiple places (i.e., more than one)
2. excessive, unnecessary, and unnatural parameter passing to log errors (using class, and only limit logging to occur at one place, i.e., the exception catching block.)

Commit before

- changing Validation(Exception-raising) fns to NOT log errors, only raise Exceptions with errmsgs ;

- and logging(Exception-handling) fns to both log to errorlog, and write lines/rows to reinsert csv.




1 Example code:


                    num_of_rows_inserted = None
                    try:
                        num_of_rows_inserted = insert_into_table(local_conn, table_name, dct_cols_values)   # Exc 3 : fail insert to db
                        print "inserted %s rows" % num_of_rows_inserted
                        self.validate_stage1_num_rows_inserted(num_of_rows_inserted, csv_row)                        # Exc 4 : inserted more than one row to table
                        local_conn.commit()
                    except Exception, e:
                        handle_stage1_dbinsert_error(self.log, path_to_reinsert_csv[INSERT_DB_ERROR], line, type(e), e, num_of_rows_inserted, csv_row, dct_cols_values)
                        local_conn.rollback()
                    else:
                        total_num_of_rows_inserted_into_table += num_of_rows_inserted





2

# VALIDATIONS - RAISE
# No need to log inside, just raise Exception with the verbose errmsg.
# The exception block outside will log the error and reinsert csv.
# --This eliminates excessive, unnecessary, and unnatural parameter passing.--
    def validate_stage1_num_rows_inserted(self, num_of_rows_inserted, csv_row):
        if num_of_rows_inserted <= 0:
            the_errmsg = "error_could_not_insert_into_local_db"
##            error_could_not_insert_into_local_db(self.log, the_errmsg, csv_row)
            raise Stage1InsertLocalDbZeroRowsInsertedException(the_errmsg)
        if num_of_rows_inserted > 1:
            the_errmsg = "error_extra_rows_inserted_into_local_db: num=%s" % num_of_rows_inserted
##            error_extra_rows_inserted_into_local_db(self.log, the_errmsg, csv_row)
            raise Stage1InsertLocalDbMultipleRowsInsertedException(the_errmsg)



No return value, only raise or don't raise to be captured by outside exception block.
Outside exception block does all the work of logging, logging the custom errmsg, at a single place.
Basically with all the values, passed in at one place only, there.




3

class MultipleCsvRowsParsedFromRawLineException(Exception): pass

class Stage1InsertLocalDbZeroRowsInsertedException(Exception): pass
class Stage1InsertLocalDbMultipleRowsInsertedException(Exception): pass

# NOT USED -- log and reinsert csv written by "handle db insert error()" in exception block.
##def write_errors_to_errorlog_and_reinsert_csv(log, the_errmsg, line_or_csv, path_to_reinsert_csv):
##    log.error(the_errmsg)
##    if isinstance(line_or_csv, basestring):
##        write_line_to_reinsert_csv(path_to_reinsert_csv, line_or_csv)
##    else:
##        try:
##            write_csv_to_reinsert_csv(path_to_reinsert_csv, line_or_csv)
##        except Exception, e:
##            write_line_to_reinsert_csv(path_to_reinsert_csv, line_or_csv)
##
##
##def error_could_not_insert_into_local_db(log, the_errmsg, line_or_csv, path_to_reinsert_csv):
##    write_errors_to_errorlog_and_reinsert_csv(log, the_errmsg, line_or_csv, path_to_reinsert_csv)
##
##def error_extra_rows_inserted_into_local_db(log, the_errmsg, line_or_csv, path_to_reinsert_csv):
##    write_errors_to_errorlog_and_reinsert_csv(log, the_errmsg, line_or_csv, path_to_reinsert_csv)


ALL OF THE ABOVE ##COMMENTED## IS NO LONGER NECESSARY.
The custom exceptions are, however.







#-------------------------------------------------------------------------------
# Name:        module1
# Purpose:
#
# Author:      leeubi
#
# Created:
# Copyright:   (c) leeubi
# Licence:     <your licence>
#-------------------------------------------------------------------------------
#!/usr/bin/env python

def form_dct_cols_values(dct, lst, csv_row):
    for i, key in enumerate(lst):
        dct[key] = csv_row[i]           # IndexError: list index out of range
    return dct


def main():
    operator_id = 1234
    csv_row = [12,]#34,56]
    dct_table_csv_mapping = {
        'active' : 1,
        'operator_id': operator_id,
    }
    lst_table_csv_mapping = [
        'extref',
        'license_size',
    ]
    dct_table_csv_mapping = form_dct_cols_values(dct_table_csv_mapping, lst_table_csv_mapping, csv_row)
    print dct_table_csv_mapping

if __name__ == '__main__':
    main()













No comments:

Post a Comment