43

I have this try/except code:

document = raw_input ('Your document name is ')

try:
    with open(document, 'r') as a:
        for element in a:
           print element

except:
    print document, 'does not exist'

How do I exit the program after I print "[filename] does not exist"? break and pass obviously don't work, and I don't want to have any crashing errors, so sys.exit is not an option.

Please ignore the try part - it's just a dummy.

alex
  • 6,818
  • 9
  • 52
  • 103
rudster
  • 1,327
  • 4
  • 14
  • 16

6 Answers6

46

Use the sys.exit:

import sys

try:
    # do something
except Exception, e:
    print >> sys.stderr, "does not exist"
    print >> sys.stderr, "Exception: %s" % str(e)
    sys.exit(1)

A good practice is to print the Exception that occured so you can debug afterwards.

You can also print the stacktrace with the traceback module.

Note that the int you return in sys.exit will be the return code of your program. To see what exit code your program returned (which will give you information about what happens and can be automated), you can do:

echo $?
Charles Menguy
  • 40,830
  • 17
  • 95
  • 117
  • 2
    If anyone is reading this 10 years later, in python 3.x you can print to stderr by: `print("spam", file=sys.stderr)`. See https://stackoverflow.com/questions/5574702/how-to-print-to-stderr-in-python – Evan Rosica Jun 08 '22 at 19:26
12

Just re-raise it. It's more friendly for developer

document = raw_input ('Your document name is ')

try:
    with open(document, 'r') as a:
        for element in a:
           print element

except:
    print document, 'does not exist'
    raise

Check python document in the Raising Exceptions section about re-raise error in except.

TylerTemp
  • 970
  • 1
  • 9
  • 9
11

Using

sys.exit(1)

is not a crashing error, it's a perfectly normal way to exit a program. The exit code of 1 is a convention that means something went wrong (you would return 0 in the case of a successful run).

Greg Hewgill
  • 951,095
  • 183
  • 1,149
  • 1,285
  • 1
    Out of curiousity, is there anything wrong with using `quit()`? Nobody seems to mention that one. – Joel Cornett Apr 15 '12 at 22:54
  • 3
    `quit()` is only intended to work in the interactive Python shell. I wouldn't use it in a program. It's not listed on http://docs.python.org/library/functions.html and I wouldn't expect it to be portable to other Python implementations. – Greg Hewgill Apr 15 '12 at 23:07
10

You can also put your code in a function and issue a return. You may call it main which you can call from your script.

def main():
    document = raw_input ('Your document name is ')

    try:
        with open(document, 'r') as a:
            for element in a:
               print element

    except:
        print document, 'does not exist'
        return

if __name__ == "__main__":
    main()
Abhijit
  • 62,056
  • 18
  • 131
  • 204
  • The problem with "return" in case of exceptions is that you won't see any error code on the command line. If you have monitoring systems, they will typically check logs as well as return code of your program, so if the program returns 0 in all cases even errors it can be tricky to maintain. – Charles Menguy Apr 15 '12 at 22:32
  • @linker You can still print an error message before returning. Not all programs need to produce output for other programs -- sometimes, just being human readable is plenty. – agf Apr 15 '12 at 22:34
  • 2
    @agf I'm just explaining what I've found to be most useful in real-world context, the best is to have both human readable and consistent return code convention. – Charles Menguy Apr 15 '12 at 22:38
  • 1
    @linker Another common convention is to `return exitcode` from `main` and then `sys.exit(main())` or similar. That way, you have a single `sys.exit`, and you have better separation in your code. – agf Apr 15 '12 at 22:42
6

In case that you are using an if statement inside a try, you are going to need more than one sys.exit() to actually exit the program.

For example, you are parsing an argument when calling the execution of some file, e.g. $./do_instructions.py 821 such as:

import sys

# index number 1 is used to pass a set of instructions to parse
# allowed values are integer numbers from 1 to 4, maximum number of instructions is 3
arg_vector = "821" # <- pretending to be an example of sys.argv[1]

if len(arg_vector) > 3:
    sys.exit(2) # <- this will take you out, but the following needs an extra step.

# for an invalid input (8). 
for i in arg_vector:

    # to validate that only numbers are passed as args.
    try:
        int(i) # <- 8 is valid so far
        
        # value (8) is not  valid, since is greater than 4
        if (int(i) == 0) or (int(i) > 4): 
            print("Values must be 1-4")
            # the following call does not takes you out from the program,
            # but rise the SystemExit exception.
            sys.exit(2) 
            
    except SystemExit: # <- needed to catch the previous as the first evaluation
        # The following parameter "2" is just for this example
        sys.exit(2) # <- needed to actually interrupt the execution of the program/script. 

    # if there is no "except SystemExit:", the following will be executed when the 
    # previous "if" statement evaluates to True and the sys.exit(2) is called.
    #
    # and the "print("Only num...") function will be called, even when the intention 
    # of it is to advice the *user* to use only numbers, since 8 is a number this
    # shouldn't be executed.
    except:
        print("Only numbers are allowed.")
        sys.exit(2)

otherwise, you want to use one try-except block for each evaluation.

Mike
  • 698
  • 1
  • 9
  • 16
-1

Probably not the best practice, but it worked for me:

import sys    

close = False
try:
    if SomethingBadHappend:
        close = True
except:
    pass
if close:
    sys.exit(1)

Close dose does not seem to work inside 'try'.

Garret45
  • 11
  • 2
  • 1
    You are essentially not using `try-except` to handle exceptions anymore, instead using `if-else`. Curious, how does it make it better, if it works at all? – jash101 Jun 25 '21 at 03:35