1

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()
Jokus
  • 11
  • 1
  • 4
  • 1
    You must use try/catch. Take a look on http://stackoverflow.com/questions/5424716/python-how-to-check-if-input-is-a-number-given-that-input-always-returns-stri – Mihai8 Feb 21 '13 at 21:50

5 Answers5

5

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`
Lev Levitsky
  • 63,701
  • 20
  • 147
  • 175
0

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
Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
0

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.

KevinA
  • 619
  • 6
  • 25
0

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

me123
  • 1
  • Don't answer unless you're fairly sure your answer is correct. Also, include more details, where that `if` goes for example and what to do if it's true. – blm Nov 15 '15 at 19:04
0

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 returning / continuing by chance would quickly become hairy.)

There is the main difference between errors caused

  • by invalid / odd user input
  • by bugs
  • by dynamic system / environment limits.

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()
kxr
  • 4,841
  • 1
  • 49
  • 32