Home > Net >  Exception Handling of multiple user inputs Python
Exception Handling of multiple user inputs Python

Time:03-06

I'm currently practicing on how to raise custom exceptions with multiple user input. How do I get to this desired output?

Terminal:
Enter assignment mark (0-20): 25
Assignment mark must be between 0 and 20
Enter assignment mark (0-20): 2
Enter project mark (0-30): 50
Project mark must be between 0 and 30
Enter project mark (0-30): 

Current output:

Enter assignment mark (0-20): 25
Assignment mark must be between 0 and 20
Enter assignment mark (0-20): 2
Enter project mark (0-30): 50
Project mark must be between 0 and 30
Enter assignment mark (0-20): 

It keeps looping back to the first question.

I appreciate anybody who can help and explain. Thanks!

Code:

class rangeError(Exception):
    def __init__(self, message):
        self.message = message

while True:
   try:
       assignment_mark = int(input("Enter assignment mark (0-20): "))
       if assignment_mark > 20 or assignment_mark < 0:
           raise rangeError("Assignment mark must be between 0 and 20")


       project_mark = int(input("Enter project mark (0-30): "))
       if project_mark > 30 or project_mark < 0:
           raise rangeError("Project mark must be between 0 and 30")


       final_exam_mark = int(input("Enter final exam mark (0-50): "))
       if final_exam_mark > 50 or final_exam_mark < 0:
           raise rangeError("Exam mark must be between 0 and 50")


       total_mark = assignment_mark   project_mark   final_exam_mark

       print(total_mark)


   except ValueError as e:
      print("Please enter integers")
   except rangeError as e:
      print(e)
   except Exception as e:
      print(e)

CodePudding user response:

Whenever an exception occurs you start with the try block again (due to while True). You never terminate or check whether the values have already been defined. When you reach the total_mark output, you also start all over again. I would suggest you retrieve the values separately using a function, to avoid duplication. Note the return mark, which exits the function and therefore the while True as soon as a proper value has been provided:

class rangeError(Exception):
    def __init__(self, message):
        self.message = message

        
def get_mark(name, val_range):
    lo, hi = val_range
    
    while True:
       try:
           mark = int(input(f"Enter {name} mark ({lo}-{hi}): "))
           if mark > val_range[1] or mark < val_range[0]:
               raise rangeError(f"{name.capitalize()} mark must be between {lo} and {hi}")

           return mark
                
       except ValueError as e:
          print("Please enter integers")
       except rangeError as e:
          print(e)
       except Exception as e:
          print(e)

assignment_mark = get_mark("assignment", [0, 20])
project_mark = get_mark("project", [0, 30])
final_exam_mark = get_mark("final exam", [0, 50])
         
total_mark = assignment_mark   project_mark   final_exam_mark 
    
print(total_mark)

CodePudding user response:

When the error occurs in the try block, Python will jump to the exception blocks and find the correct error to raise. When the error is handled, it loops to the top of the while-block. That is why your code is starting over.

There are a couple of ways to handle it. One is to have a while loop for each input. Another way is to set variables in your global scope that hold the values of assignment_mark, project_mark, and final_exam_mark. You can then check if the value exists and skip to the correct chunk of code. Since all three of your checks are for a range, you can wrap the check as a function to shorten you code.

class RangeError(Exception):
    def __init__(self, min_, max_):
        self.min_ = min_
        self.max_ = max_

    def __str__(self):
        return f'Input value must be between {self.min_} and {self.max_}.'

def range_check(x, min_, max_):
    if min_ <= x <= max_:
        return x
    raise RangeError(min_, max_)

def get_input_within_range(input_msg, min_, max_):
    mark = range_check(int(input(f"{input_msg} ({min_}-{max_}): ")), min_, max_)
    return mark


assignment_mark = None
project_mark = None
final_exam_mark = None
total_mark = None

while True:
    try:
        if assignment_mark is None:
            assignment_mark = get_input_within_range("Enter assignment mark", 0, 20)
        if project_mark is None:
            project_mark = get_input_within_range("Enter project mark", 0, 30)
        if final_exam_mark is None:
            final_exam_mark = get_input_within_range("Enter final exam mark", 0, 50)
        if total_mark is None:
            total_mark = assignment_mark   project_mark   final_exam_mark
            print(f'Total mark is: {total_mark}')
        else:
            quit_ans = input("Type 'Q' to quit, anything else to restart: ")
            if quit_ans.upper() == 'Q':
                break
            else:
                assignment_mark = None
                project_mark = None
                final_exam_mark = None
                total_mark = None

    except ValueError as e:
        print("Please enter integers")
    except RangeError as e:
        print(e)
    except Exception as e:
        print(e)
  • Related