0

Below is my code to calculate calories based on input, after the print statements I want to exit the code and loop infinitely until the user inputs the right values.

import sys
def main():
    while True:
        try: 
            print("Please enter Age,Weight,Heart Rate and Workout Time ")
            Age,Weight,HR,Time = map(eval,input().split(' '))
            men = ( (Age * 0.2017) - (Weight * 0.09036) + (HR * 0.6309) - 55.0969 ) * Time / 4.184
            women =  ( (Age * 0.074) - (Weight * 0.05741) + (HR * 0.4472) - 20.4022 ) * Time / 4.184
            print("Men:",men," Calories \nWomen:",women,"Calories \n")
            exit()
        except:
            print("Please enter numbers only \n \n")

if __name__ == '__main__':
    main()

The code goes to the except even if the input values are right and does not exit the code, what am I missing?

4
  • 1
    You don't need to exit, you need to break from the loop. Commented Sep 3, 2021 at 2:55
  • 1
    Don't map(eval, ...) do map(float, input().split(' ')) instead Commented Sep 3, 2021 at 2:57
  • 2
    Advice: the only code that should go inside a try block is the code that can raise an exception. Everything else should be outside the try. Commented Sep 3, 2021 at 2:57
  • 1
    Welcome to SO, Swayam. I appreciate that you provided working (minimal-ish) code and described what goes wrong! Commented Sep 3, 2021 at 2:59

1 Answer 1

5

exit() (some forms; it's not actually supposed to be used in scripts, so it can be overridden to do weird things; you want sys.exit()) is implemented by raising a SystemExit exception (exiting without bubbling out would mean cleanup blocks in finally and with statements don't execute, which would be bad, so they use the exception mechanism to do the cleanup). SystemExit is special in two ways:

  1. It doesn't dump a traceback and exit with a fixed status 1 if unhandled (it just silently exits the program with the status code it was provided)
  2. It's not a child of Exception, so except Exception:, which is very broad, still won't catch it

But you used a bare except, which catches everything, including SystemExit. Don't do that.

In this specific case, the correct solution is really to just replace exit() with break, which will pop you out of the while loop and allow the program to run to completion with no need for an exception at all. And use a narrower except clause while you're at it.

Sign up to request clarification or add additional context in comments.

5 Comments

good answer. do you have a citation for "not actually supposed to be used in scripts"? I assume you're referring to a PEP of some sort? (I'm just curious, no criticism here)
@en_Knight: It's one of the constants added by the site module, which is documented with: "The site module (which is imported automatically during startup, except if the -S command-line option is given) adds several constants to the built-in namespace. They are useful for the interactive interpreter shell and should not be used in programs." It's not guaranteed to exist, and stuff like IPython overrides it in ways that might subtly break code. sys.exit() has neither problem.
thanks, I didn't know that! Amusingly, the first hit when i google'd it had a comment "sys.exit() is not a reliable way to close down. If it is called inside a thread, it will terminate only that thread unless it is in the main thread" (from stackoverflow.com/questions/19747371/…). But that's (A) way above what the OP is trying to do and (B) a little bit picky, since you should probably have a more sophisticated shut down procedure, IMO, in something multithreaded and complicated
@en_Knight: Yeah, but nothing save os._exit will end a multithreaded program with other running non-daemon threads. And you almost never want os._exit because of that behavior; it doesn't throw an exception, it just ends the process now, and doesn't invoke all the finally and with cleanup that's supposed to be "guaranteed" to run. os._exit burns the world down. If sys.exit isn't doing what you want, it's because you're not using daemon threads appropriately, or your main thread is failing to tell your non-daemon threads to stop cleanly when it's exiting, or both.
yup, I agree with all that

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.