27

I have following script in Python 3.2.3:

try:
    file = open('file.txt', 'r')
except IOError:
    print('There was an error opening the file!')
    sys.exit()

#more code that is relevant only if the file exists

How do I exit gracefully, if the file doesn't exist (or there is simply an error opening it)?

I can use exit(), but that opens a dialog panel asking if I want to kill the application.

I can use sys.exit(), but that raises a SystemExit exception which doesn't looks great in output. I get

Traceback (most recent call last):   
File "file", line 19, in <module>
    sys.exit() SystemExit

I can use os.exit(), but that kills the Python on C level, without any cleanups I might be performing.

I can use a boolean variable and wrap all subsequent code in if... but that is ugly, and this is not the only check I am performing. So I would have like six nested ifs...

I just want to print the 'There was an error...' and exit. I am working in IDLE.

Jakub Zaverka
  • 8,816
  • 3
  • 32
  • 48
  • 3
    This looks like the correct way to do it. Generally, you don't see the `SystemExit` exception (unless you're catching it someplace else which you probably shouldn't be) ... I'm not sure what you're talking about it looking good in the output. – mgilson Nov 16 '12 at 21:51
  • 3
    You might be able to `return` from the current function. – Nathan Villaescusa Nov 16 '12 at 21:51
  • Raise an exception of your own that gets caught at top-level, or caught and rethrown where you need cleanup. (That said, you shouldn't really need much explicit cleanup that unwinding the stack won't do for you.) – millimoose Nov 16 '12 at 21:51
  • 1
    Better, call `sys.exit()` and catch the `SystemExit` at the top level. (I don't see SystemExit myself; what environment are you running in?) – Russell Borogove Nov 16 '12 at 21:52
  • @RussellBorogoveI am using IDLE. – Jakub Zaverka Nov 16 '12 at 21:59
  • have you tried calling `sys.exit(0)`? – Cameron Sparr Nov 16 '12 at 22:03
  • @COpython yes, it still prints the SystemExit – Jakub Zaverka Nov 16 '12 at 22:06
  • 4
    @JakubZaverka - Just run your script outside of IDLE then and you can see that `sys.exit` won't display `SystemExit`. IDLE does so that you know if the program finished or exited abnormally. – lqc Nov 16 '12 at 22:07

2 Answers2

21

This is a very graceful way to do it. The SystemExit traceback won't be printed outside of IDLE. Optionally you can use sys.exit(1) to indicate to the shell that the script terminated with an error.

Alternatively you could do this in your "main" function and use return to terminate the application:

def main():
    try:
        file = open('file.txt', 'r')
    except IOError:
        print('There was an error opening the file!')
        return

    # More code...

if __name__ == '__main__':
    main()

Here the main execution code of the application is encapsulated in a single function called "main", then executed only if the script is executed directly by the Python interpreter, or in other words, if the script it not being imported by another script. (The __name__ variable is set to "__main__" if the script is being executed directly from the command line. Otherwise it will be set to the name of the module.)

This has the advantage of gathering all script execution logic into a single function, making your script cleaner, and enables you to cleanly exit your script using the return statement, just like in most compiled languages.

Hubro
  • 56,214
  • 69
  • 228
  • 381
2

Using sys.exit() is fine. If you're that concerned with output, you can always add an extra try/except block within your error handling section to catch the SystemExit and stop it from being directed to console output.

try:
    file = open('file.txt', 'r')
except IOError:
    try:
        print('There was an error opening the file!')
        sys.exit()
    except SystemExit:
        #some code here that won't impact on anything
Lorcan O'Neill
  • 3,303
  • 1
  • 25
  • 24
  • This solution does not work as the `except SystemExit:` statement will ignore the the sys.exit() call thus desired exit. – Aaron Ciuffo Jun 27 '20 at 15:06