Reputation: 11
I have this simple project to do. This is the code I have so far, it works perfectly fine. But if someone types in a letter or an unknown symbol, the program crashes. How can I make this error proof and display or print a message if the wrong thing is entered?
def excercise5():
print("Programming Excercise 5")
print("This program calculates the cost of an order.")
pound = eval(input("Enter the weight in pounds: "))
shippingCost = (0.86 * pound) + 1.50
coffee = (10.50 * pound) + shippingCost
if pound == 1:
print(pound,"pound of coffee costs $", coffee)
else:
print(pound,"pounds of coffee costs $", coffee)
print()
excercise5()
Upvotes: 1
Views: 7117
Reputation: 5539
Exceptions are the way to comfortably route and handle errors in non-trivial programs. But a clear concept is helpful to not make a random hack out of that when programs grow.
(E.g. catching builtin ValueError
far away or return
ing / continuing by chance would quickly become hairy.)
There is the main difference between errors caused
A reasonable way of separating, routing and handling these errors is:
(A) Catch or compare for user input errors very early near the point of potential happening. React immediately for simple recoveries / repetitions. Otherwise (for breaking out) convert to an enriched exception which can be catched and distinguished further down or at the bottom of the call stack (or by the default handler sys.excepthook
)
(B) Let crash down bug exceptions to the bottom of the call stack - unhandled; or possibly initiate comfortable bug presentation and feedback action.
(C) For system environment errors choose an approach between (A) and (B) depending on how much context, detail & comfort info you want to be present at the current stage of development.
This way this could become a scalable pattern for user oriented error handling in your example:
# Shows scalable user oriented error handling
import sys, traceback
DEBUG = 0
class UserInputError(Exception):
pass
def excercise5():
print("Programming Excercise 5")
print("This program calculates the cost of an order.")
# NOTE: eval() and input() was dangerous
s = input("Enter the weight in pounds: ")
try:
pound = float(s)
except ValueError as ev:
raise UserInputError("Number required for weight, not %r" % s, ev)
if pound < 0:
raise UserInputError("Positive weight required, not %r" % pound)
shippingCost = (0.86 * pound) + 1.50
coffee = (10.50 * pound) + shippingCost
if pound == 1:
print(pound,"pound of coffee costs $", coffee)
else:
print(pound,"pounds of coffee costs $", coffee)
print()
if __name__ == '__main__':
try:
excercise5()
except UserInputError as ev:
print("User input error (please retry):")
print(" ", ev.args[0])
if DEBUG and len(ev.args) > 1:
print(" EXC:", ev.args[1], file=sys.stderr)
except (EnvironmentError, KeyboardInterrupt) as ev:
print("Execution error happend:")
print(" ", traceback.format_exception_only(ev.__class__, ev)[0])
except Exception:
print("Please report this bug:")
traceback.print_exc()
Upvotes: 0
Reputation: 1
Could you not use ascii. eg turn the string into a numerical value then ignore results which aren't within your numerical window eg 'if (c <= 47 and c >= 57):'. This should stop it crashing. I think:P
Upvotes: 0
Reputation: 65811
I'd advise against using eval
. It is not good from the security point of view. Just do an explicit conversion to the desired type:
pound = float(input("Enter the weight in pounds: "))
To process invalid input:
try:
pound = float(input("Enter the weight in pounds: "))
except ValueError:
print('Invalid input.')
return
# the rest of the code
Or:
try:
pound = float(input("Enter the weight in pounds: "))
except ValueError:
print('Invalid input.')
else:
# the rest of the code
You can also wrap the input in an infinite loop that would terminate on successful conversion:
while True:
try:
pound = float(input("Enter the weight in pounds: "))
except ValueError:
print('Invalid input. Try again.')
else:
break
# do the rest with `pound`
Upvotes: 5
Reputation: 629
Surround the statement witha try/except
def excercise5():
print("Programming Excercise 5")
print("This program calculates the cost of an order.")
pound = eval(input("Enter the weight in pounds: "))
try:
shippingCost = (0.86 * pound) + 1.50
coffee = (10.50 * pound) + shippingCost
if pound == 1:
print(pound,"pound of coffee costs $", coffee)
else:
print(pound,"pounds of coffee costs $", coffee)
except ValueError:
print("Please Enter a valid number")
print()
I should note: There is no way to "Error Proof" something, much like bullet proofing is impossible, a big enough bullet will penetrate anything, same with coding. All you can do is write good code. Nothing is absolute in coding.
Upvotes: 0
Reputation: 1123400
Use exception handling.
Python doesn't crash when someone gives you invalid input, it throws an exception instead. You can catch such exceptions and handle them instead of letting python exit the program.
In this case, since you only want a floating point number you really should not be using eval()
; that will take a lot of different inputs and will throw a lot of different exceptions.
Use the float()
function instead, it will only throw a ValueError
if you give it incorrect input. Then catch that and display an error message:
try:
pound = float(input("Enter the weight in pounds: "))
except ValueError:
print('Not a valid number!')
return
Upvotes: 0