Integrating Exception Handling for Data Types

System: O365

IDE: JupyterLab

Language: Python version 3.7.3

Library: pandas version 1.0.1

Data source: personally built

Hello, I am wondering if anyone knows how I can refactor my code to integrate exception handling to create a data validation scheme for an entry form. Essentially I have four variables I need to protect and I am having a hard time trying to figure out should data validation be integrated within the “class-functions (bank.py and client.py)” or within the “source-code (main.py)” itself. The four variables that require validation are:

Variables Needing Validation:

  1. Name: as a str
  2. Address: as a str or validated against some address API for verification if available?
  3. Account: as either checking or savings
  4. Deposit amount: as a positive float

Code (input screen):

exception

Code (first class: bank.py):

class Bank:

name = 'Springboard Federal Credit Union'
clients = []

def update_db(self, client):
    """This function updates the internal memory database with clients account information.
    
    Parameters
    ----------
    self : is the autogenerated index in the database to house account details.
    client : is the client details from the client file
    
    Returns
    ----------
    Stores account details and returns the account information for indexing later.
    """
    self.clients.append(client)

def authentication(self, name, account_number):
    """This function validates users credentials to allow retrieval of information later.
    
    Parameters
    ----------
    name : takes in the full name of the account holder as a str.
    account_number : is the autogenerated random account_number from client.py file
    
    Returns
    ----------
    Stores account details and returns the account information for indexing later.
    """
    for i in range(len(self.clients)):
        if name in self.clients[i].account.values() and account_number in self.clients[i].account.values():
            print()
            print("Authentication successful!")
            print("==========================================")
            return self.clients[i]

Code (second class: client.py):

from random import randint

class Client:

    account = {}

    def __init__(self, name, address, account, deposit):
        """This function instantiates a new account with five parameters: random generated account number, 
        name, address, account, and initial deposit.
        
        Parameters
        ----------
        self : is an autogenerated random account_number to instantiate a new account number as a num
        name : takes in the full name of the account holder as a str
        address : takes in the full address of the account holder as a str
        account : takes in the account type: (checking or savings) as a str
        deposit : takes in a num as a float
        
        Returns
        ----------
        Stores account details 
        """
        self.account['account_number'] = randint(10000, 99999)
        self.account['name'] = name
        self.account['address'] = address
        self.account['account type'] = account
        self.account['balance'] = deposit

    def withdraw(self, amount):
        """This function decreases balance number by some applied amount.
        
        Parameters
        ----------
        amount : new amount to be subtracted from balance
        
        Returns
        ----------
        balance -= amount
        """
        if self.account['balance'] >= amount:
            self.account['balance'] -= amount
            print()
            print("The sum of {} has been withdrawn from your account balance.".format(amount))
            self.balance()
        else:
            print()
            print("Insufficient funds!")
            self.balance()

    def deposit(self, amount):
        """This function increases balance number by some applied amount.
        
        Parameters
        ----------
        amount : new amount to be added to balance
        
        Returns
        ----------
        balance += amount
        """        
        self.account['balance'] += amount
        print()
        print("The sum of {} has been added to your account balance.".format(amount))
        self.balance()

    def balance(self):
        """This function presents the balance.
        
        Parameters
        ----------
        self.account : the accont number
        
        Returns
        ----------
        The current balance from the stated account
        """
        print()
        print("Your current account balance is: {} ".format(self.account['balance']))

Code (source code: main.py):

## Import files
from client import Client
from bank import Bank

# Setting Bank function to a variable
bank = Bank()

# Spelling out welcome banner
welcome = "Welcome to {}!".format(bank.name)
print(f' --------------------------------------------n {welcome}n --------------------------------------------')

# Running input prompt
running = True
while running:
    print()
    print("""Choose an option:
    
    1. Open a new bank account
    2. Access existing bank account
    3. Exit terminal
    """)

    choice = int(input("1, 2 or 3: "))

    # Selected if option 1: Open new bank account is chosen
    try:
        if choice == 1:
            print(f' nTo create a new account, please provide the information below.n ')
            client = Client(input("Name: "), str(input("Address: ")), str(input("Account Type (checking or savings): ")), float(input("Deposit amount: ")))
            bank.update_db(client)
            client_account = client.account['account_number']
            print(f'_______________________________________________________________n<<Account created successfully! Your account number is: {client_account}>>')

        # Selected if option 2: Access existing bank account
        elif choice == 2:
            print(f' nTo access your account, please enter your access information.n ')
            name = input("Name: ")
            account_number = int(input("Account number: "))
            current_client = bank.authentication(name, account_number)
            if current_client:
                print()
                print("Welcome {}!".format(current_client.account['name']))
                acc_open = True
                while acc_open:
                    print()
                    print("""Choose an option:

        1. Withdraw
        2. Deposit
        3. Balance
        4. Exit Account Window
                        """)
                    acc_choice = int(input("1, 2, 3 or 4: "))

                    if acc_choice == 1: # Selected if sub-option 1: Withdraw
                        print()
                        current_client.withdraw(int(input("Withdraw amount: ")))
                    elif acc_choice == 2: # Selected if sub-option 2: Deposit
                        print()
                        current_client.deposit(int(input("Deposit amount: ")))
                    elif acc_choice == 3:  # Selected if sub-option 3: Balance
                        print()
                        current_client.balance()
                    elif acc_choice == 4:  # Selected if sub-option 4: Exit Account Window
                        current_client = ''
                        acc_open = False
            else:
                print(f' n-Authentication failed!n-Reason: Account not found.n----nDo you want to try again? If not, ')
                continue

        # Selected if option 3: Exit the terminal
        elif choice == 3:
            running = False
    
    # If anything breaks within the try statement (i.e. an individual tries to pass in a letter for an account number) run this general exception
    except Exception:
        print('-- We apologize for the inconvenience. --n-- Due to security reasons suspicious activity has occured and we are terminating this session. --nPlease try back at a later time.')
    
    # Do this no matter what happens within the program
    finally:
        print(f'==========================================nThank you for allowing us to service you!n==========================================')

Problem

I need to understand a way to integrate exception handling to help validate the entries so not to contaminate my database.

Steps Taken

  1. I reviewed the following post by Srini at: Exception handling – how to handle invalid datatype in user input?

  2. It seems like this is what I need however I am trying to find out should I integrate this into the class functions or should I build it into the: try, except, finally “exception handling” within the main source code above.

Any assistance will be greatly appreciated as I have been working on this for a while now. 🙂

Answer

Please see the answer below if anyone else gets stuck on this or needs some help similar to this problem’s use-case. Big thanks to @xtlc!

first class

class Bank:

    name = 'Springboard Federal Credit Union'
    clients = []
    valid_account_types= ['checking', 'savings']

    def validate_client(self, client):
        """This function validates the account type and initial deposit entered by the user.
        
        Parameters
        ----------
        self : is the autogenerated index in the database to house client details.
        client : is the client details from the client file.
        
        Returns
        ----------
        Returns a printed statement if account is not valid.
        Returns a printed statement if the user tries to pull a balance less than 0.
        """
        account_type = client.account['account_type']
        if (account_type not in self.valid_account_types):
            print("Not a valid account_type")
            return False
        balance = client.account['balance']
        if (balance <= 0.0):
            print("you must have a positive balance to create an account")
            return False
        return True

    def update_db(self, client):
        """This function updates the internal memory database with clients account information.
        
        Parameters
        ----------
        self : is the autogenerated index in the database to house account details.
        client : is the client details from the client file.
        
        Returns
        ----------
        Stores account details and returns the account information for indexing later.
        """
        if (self.validate_client(client)):
            self.clients.append(client)
            return True
        else:
            print("can not create account, one or more information are not correct")
            return False

    def authentication(self, name, account_number):
        """This function validates users credentials to allow retrieval of information later.
        
        Parameters  
        ----------
        name : takes in the full name of the account holder as a str.
        account_number : is the autogenerated random account_number from client.py file.
        
        Returns
        ----------
        Stores account details and returns the account information for indexing later.
        """
        for i in range(len(self.clients)):
            client = self.clients[i]
            if (name == client.account['name']) and (account_number == client.account['account_number']):
                print()
                print("Authentication successful!")
                print("==========================================")
                return self.clients[i]

second class

from random import randint

class Client:

    account = {}

    def __init__(self, name, address, account, deposit):
        """This function instantiates a new account with five parameters: random-generated account number, 
        name, address, account, and initial deposit.
        
        Parameters
        ----------
        self : is an autogenerated random account_number to instantiate a new account number as a num
        name : takes in the full name of the account holder as a str
        address : takes in the full address of the account holder as a str
        account : takes in the account type: (checking or savings) as a str
        deposit : takes in a num as a float
        
        Returns
        ----------
        Stores account details. 
        """
        self.account['account_number'] = randint(10000, 99999)
        self.account['name'] = name.strip()
        self.account['address'] = address.strip()
        self.account['account_type'] = account.strip()
        self.account['balance'] = deposit

    def withdraw(self, amount):
        """This function decreases balance number by some applied amount.
        
        Parameters
        ----------
        amount : new amount to be subtracted from balance
        
        Returns
        ----------
        balance -= amount
        """
        if self.account['balance'] >= amount:
            self.account['balance'] -= amount
            print()
            print("The sum of {} has been withdrawn from your account balance.".format(amount))
            self.balance()
        else:
            print()
            print("Insufficient funds!")
            self.balance()

    def deposit(self, amount):
        """This function increases balance number by some applied amount.
        
        Parameters
        ----------
        amount : new amount to be added to balance.
        
        Returns
        ----------
        balance += amount
        """        
        self.account['balance'] += amount
        print()
        print("The sum of {} has been added to your account balance.".format(amount))
        self.balance()

    def balance(self):
        """This function presents the balance.
        
        Parameters
        ----------
        self.account : the accont number
        
        Returns
        ----------
        The current balance from the stated account
        """
        print()
        print("Your current account balance is: {} ".format(self.account['balance']))

main source-code

## Import files
from client import Client
from bank import Bank

# Setting Bank function to a variable
bank = Bank()

# Spelling out welcome banner
welcome = "Welcome to {}!".format(bank.name)
print(f' --------------------------------------------n {welcome}n --------------------------------------------')

# Running input prompt
running = True
while (running==True):
    print()
    print("""Choose an option:
    
    1. Open a new bank account
    2. Access existing bank account
    3. Exit terminal
    """)
    
    # Build the menu selector
    choice = int(input("1, 2 or 3: "))

    # Build outer try statment to encapsulate the program
    try:
        # Selected if option 1: Open new bank account is chosen
        if choice == 1:
            print(f' nTo create a new account, please provide the information below.n ')
            client = Client(input("Name: "), str(input("Address: ")), str(input("Account Type (checking or savings): ")), float(input("Deposit amount: ")))
            response=bank.update_db(client)
            
            # Validate that account_number matches
            if (response==True):
                client_account = client.account['account_number']
                print(f'_______________________________________________________________n<<Account created successfully! Your account number is: {client_account}>>')

        # Selected if option 2: Access existing bank account
        elif choice == 2:
            
            # Build inter try statement to access account and validate account_number
            try:
                print(f' nTo access your account, please enter your access information.n ')
                name = input("Name: ")
                account_number = int(input("Account number: "))
            except Exception:
                print("Your account number is a five digit number")

            current_client = bank.authentication(name, account_number)
            if current_client:
                print()
                print("Welcome {}!".format(current_client.account['name']))
                acc_open = True
                while (acc_open==True):
                    print()
                    print("""Choose an option:
        1. Withdraw
        2. Deposit
        3. Balance
        4. Exit Account Window
                        """)
                    acc_choice = int(input("1, 2, 3 or 4: "))
                    
                    # Selected if sub-option 1: Withdraw
                    if acc_choice == 1: 
                        print()
                        
                        # Add in exception handling for withdrawal issues
                        try:
                            withdraw = int(input("Withdraw amount: "))
                            if (withdraw <= 0):
                                raise Exception()                            
                            else:
                                current_client.withdraw(withdraw)
                        except Exception:
                            print("Your withdrawal amount should be a positive integer.")
                    
                    # Selected if sub-option 2: Deposit
                    elif acc_choice == 2: 
                        print()
                        
                        # Add in exception handling for withdrawal issues
                        try:
                            deposit = int(input("Deposit amount: "))
                            if (deposit <= 0):
                                raise Exception("")
                            else: 
                                current_client.deposit(deposit)
                        except Exception:
                            print("Your deposit amount should be a positive integer.")
                    
                    # Selected if sub-option 3: Balance
                    elif acc_choice == 3:  
                        print()
                        current_client.balance()
                    
                    # Selected if sub-option 4: Exit Account Window
                    elif acc_choice == 4:  
                        current_client = ''
                        acc_open = False    
                    else:
                        print("only entering 1,2, 3 and 4 is allowed")
            
            # Inner loop else statement if authentication fails
            else:
                print(f' n-Authentication failed!n-Reason: Account not found.n----nDo you want to try again? If not, ')
                continue

        # Selected if option 3: Exit the terminal
        elif choice == 3:
            running = False
        
        # Outer loop else to catch failures if anything is selected outside 1 through 3
        else:
            print("only entering 1,2 and 3 is allowed")
        
    # If anything breaks within the try statement (i.e. an individual tries to pass in a letter for an account number) run this general exception
    except Exception:
        print('-- We apologize for the inconvenience. --n-- Due to security reasons suspicious activity has occured and we are terminating this session. --nPlease try back at a later time.')
    
    # Do this no matter what happens within the program
    finally:
        print(f'==========================================nThank you for allowing us to service you!n==========================================')