Reputation: 517
I am writing a program that calculates the compound interest using the formula: P(1 + i)n
The principal, interest and number of years are obtained from the user input.
I have written the following method:
def is_valid_entries(principle, int_rate, years):
try:
#Convert the inputs from string to respective data type
principal_float = float(principle)
rate_float = float(int_rate)
years_int = int(years)
if not (0 < rate_float < 1.0):
return False, "The interest rate must be between 0.00 to 1.00"
return True, (principal_float, rate_float, years_int)
except ValueError:
return False, "Could not convert data to the appropriate data type"
except:
return False, "Unknown error"
However, my issue is I want to be very specific when i report exception. For instance, if there's a conversion error on principal, I want to report that there's an error in converting the principal and the same logic follows with interest rate and years. Please let me know how this can be done in exception handling or if there's a better way to write this.
Upvotes: 0
Views: 115
Reputation: 19395
In general, you will have to minimize your try
block to specific lines, to look something like this:
def is_valid_entries(principle, int_rate, years):
#Convert the inputs from string to respective data type
try:
principal_float = float(principle)
except ValueError:
return False, "Could not convert principal to the appropriate data type"
try:
rate_float = float(int_rate)
except ValueError:
return False, "Could not convert rate to the appropriate data type"
try:
years_int = int(years)
except ValueError:
return False, "Could not convert years to the appropriate data type"
if not (0 < rate_float < 1.0):
return False, "The interest rate must be between 0.00 to 1.00"
return True, (principal_float, rate_float, years_int)
Of course, as you can see this is horrible. A hint for improvement is repeating code == functions
, so a good idea can be to wrap this in a function:
def number_conversion(string, type, name):
try:
return type(string)
except ValueError:
raise ValueError(f"Could not convert {name} to {type().__class__.__name__}")
And now your main code can look like:
def is_valid_entries(principle, int_rate, years):
#Convert the inputs from string to respective data type
try:
principal_float = number_conversion(principle, float, "principle")
rate_float = number_conversion(int_rate, float, "rate")
years_int = number_conversion(years, int, "years")
except ValueError as ve:
return False, ve.message
if not (0 < rate_float < 1.0):
return False, "The interest rate must be between 0.00 to 1.00"
return True, (principal_float, rate_float, years_int)
This way you get a specific message according to each input.
* I removed the blank except
as there are no other exceptions that will rise in this code
Upvotes: 1
Reputation: 977
You're just missing the "raise" keyword. You probably don't want to wrap this whole thing in a try block like that, you just want to use raise instead of return in some places.
For example where you have:
if not (0 < rate_float < 1.0):
return False, "The interest rate must be between 0.00 to 1.00"
You could instead say:
if not (0 < rate_float < 1.0):
raise ValueError("The interest rate must be between 0.00 to 1.00")
That will raise a value error with that message that you are returning as a string. If someone calls your function in a try block, they can handle the ValueError exception.
https://docs.python.org/3/tutorial/errors.html
Upvotes: 2