Home > Enterprise >  Python Exception Handling - BMI CALCULATOR
Python Exception Handling - BMI CALCULATOR

Time:09-07

I am coding a BMI calculator in python and wanted to add exception handling. I created two functions 1. a height converter that converts the height to feet or meters depending on the user's input, and a weight converter that converts the user's weight to kg or pounds depending on the input. The def height_converter(h) and weight_converter(w) functions don't restart when the user types in the wrong input, unlike the codes below it which asks only for the weight and height. Also, the BMI variable returns an error, I don't know what to do again

# BMI CALCULATOR IN PYTHON
import os
from datetime import datetime
# define our clear function
def clear():
    # for windows
    if os.name == 'nt':
        os.system('cls')
    # for mac and linux(here, os.name is 'posix')
    else:
        _ = os.system('clear')
def weight_converter(w):
    while True:
        try:
            global converted
            converted = 0
            weight_unit = input("What is the weight unit Kgs or Lbs: ")
            if weight_unit.upper() == "KG":
                converted = w / 1
                print("weight in kg is: ", converted)
            elif weight_unit.upper() == "LBS":
                converted = w / 2.2
                print("weight in kg is: ", converted)
            else:
                raise ValueError(weight_unit)
            break
        except (ValueError, IOError, IndexError):
            print("ERROR")
            return converted
def height_converter(h):
    while True:
        try:
            height_unit = input("what is the height unit meters or feet: ")
            if height_unit.upper() == "METERS":
                converted = h / 1
                print("height in meters is: ", converted)
            elif height_unit.upper() == "FEET":
                converted = h / 3.281
                print("height in meters is: ", converted)
            break
        except(ValueError,IOError,IndexError):
            print("ERROR")
        return converted
while True:
    try:
        age = input("How old are you? ")
        age = int(age)

        weight = input("What is your weight: ")
        weight = float(weight)
        wconverted = weight_converter(weight)
      
        height = input("What is your height: ")
        height = float(height)
        hconverted = height_converter(height)
        break
    except ValueError:
        # os.system(clock_settime)
        print("No valid integer! Please try again ...")
        clear()
BMI = float(wconverted / (hconverted ** 2))
print("Your BMI is: ", BMI, "as of ", date) 
print("You are using a", os.name, "system")

CodePudding user response:

In your weight_converter function you are only going to return the converted value when the user enters bad input. In Python the indention determines in which code block the statement will belong. You need to put the return statement at the same indention level as your while True: That puts it outside the while loop and it'll basically happen after one of you breaks.

The height_converter function has a similar problem.

Also you only raise the ValueError in one of these functions and since you catch them in the except block they will not propagate up to the caller.

Exception handling for this code seems like unnecessary added complexity. Raising a ValueError simply to make the next line of code do something different is overkill and confusing. Here is a much simpler version of your weight_converter function.

def weight_converter(w):
    while True:
        weight_unit = input("What is the weight unit Kgs or Lbs: ")
        if weight_unit.upper() == "KG":
            conversion = 1.0
            break
        elif weight_unit.upper() == "LBS":
            conversion = 2.2
            break
        else
            print("ERROR")
    converted = w / conversion
    print("weight in kg is: ", converted)
    return converted

Uncaught exceptions propagate up the call stack until they are caught by an except block. If they are not caught they cause the interpreter to halt the program and usually print a stack trace. If this code causes exceptions they will be caught by the exception handler that you have in the caller. If you catch them in this function they will never make it up to the caller.

CodePudding user response:

Testing out your code, in the conversion functions, the return operation at the end of the code blocks were not actually being executed because of where it logically resided within the indentation of the code block. So, you were effectively returning a "None" to the statements calling those functions.

With that in mind, following is your code with some tweaks to return a converted value from the weight and height conversion functions.

# BMI CALCULATOR IN PYTHON
import os
from datetime import date     # FYI, I revised this a bit as well for the date
# define our clear function
def clear():
    # for windows
    if os.name == 'nt':
        os.system('cls')
    # for mac and linux(here, os.name is 'posix')
    else:
        _ = os.system('clear')
def weight_converter(w):
    while True:
        try:
            global converted
            converted = 0
            weight_unit = input("What is the weight unit Kgs or Lbs: ")
            if weight_unit.upper() == "KG":
                converted = w / 1
                print("weight in kg is: ", converted)
                return converted            # Made sure a decimal value was being returned
            elif weight_unit.upper() == "LBS":
                converted = w / 2.2
                print("weight in kg is: ", converted)
                return converted            # Same here
            else:
                raise ValueError(weight_unit)
            break
        except (ValueError, IOError, IndexError):
            print("ERROR")
            return 0.0
def height_converter(h):
    while True:
        try:
            height_unit = input("what is the height unit meters or feet: ")
            if height_unit.upper() == "METERS":
                converted = h / 1
                print("height in meters is: ", converted)
                return converted            # And here
            elif height_unit.upper() == "FEET":
                converted = h / 3.281
                print("height in meters is: ", converted)
                return converted            # And finally here
            break
        except(ValueError,IOError,IndexError):
            print("ERROR")
        return 1.0
while True:
    try:
        age = input("How old are you? ")
        age = int(age)

        weight = input("What is your weight: ")
        weight = float(weight)
        wconverted = weight_converter(weight)
      
        height = input("What is your height: ")
        height = float(height)
        hconverted = height_converter(height)
        break
    except ValueError:
        # os.system(clock_settime)
        print("No valid integer! Please try again ...")
        clear()
BMI = float(wconverted / (hconverted ** 2))
print("Your BMI is: ", BMI, "as of ", date.today())     # You had not defined the variable "date"
print("You are using a", os.name, "system")

I applied a brute force method to make sure a value was being returned. Alternatively, you might refine that last return in your function block to only have one return, but I just wanted to avoid possible scope issues in providing a quick tweak.

That produced the following sample results.

@Una:~/Python_Programs/BMI$ python3 Calculator.py 
How old are you? 66
What is your weight: 170
What is the weight unit Kgs or Lbs: lbs
weight in kg is:  77.27272727272727
What is your height: 5.83333
what is the height unit meters or feet: feet
height in meters is:  1.7779122218835721
Your BMI is:  24.445876294351564 as of  2022-09-06
You are using a posix system

Give that a try.

  • Related