views:

591

answers:

6

Long story short, I have a substantial Python application that, among other things, does outcalls to "losetup", "mount", etc. on Linux. Essentially consuming system resources that must be released when complete.

If my application crashes, I want to ensure these system resources are properly released.

Does it make sense to do something like the following?

def main():
    # TODO: main application entry point
    pass

def cleanup():
    # TODO: release system resources here
    pass

if __name__ == "__main__":
    try:
        main()
    except:
        cleanup()
        raise

Is this something that is typically done? Is there a better way? Perhaps the destructor in a singleton class?

+2  A: 

Application wide handler is fine. They are great for logging. Just make sure that the application wide one is durable and is unlikely to crash itself.

Darren Kopp
+10  A: 

I like top-level exception handlers in general (regardless of language). They're a great place to cleanup resources that may not be immediately related to resources consumed inside the method that throws the exception.

It's also a fantastic place to log those exceptions if you have such a framework in place. Top-level handlers will catch those bizarre exceptions you didn't plan on and let you correct them in the future, otherwise, you may never know about them at all.

Just be careful that your top-level handler doesn't throw exceptions!

Bob King
Top-level exception handlers are useful in GUI applications. Uncaught exceptions thrown in event handlers will show up in the console, but in general will not crash the program (e.g. in PyGTK and PyQt), this may go unnoticed. If you show an error dialog in the handler, you don't have that problem.
Torsten Marek
I would also suggest that you put them in console apps that do batch processing. I have them send out an email so we can be notified of any problems, but at the very least it could log it.
Eric Labashosky
+7  A: 

A destructor (as in a __del__ method) is a bad idea, as these are not guaranteed to be called. The atexit module is a safer approach, although these will still not fire if the Python interpreter crashes (rather than the Python application), or if os._exit() is used, or the process is killed aggressively, or the machine reboots. (Of course, the last item isn't an issue in your case.) If your process is crash-prone (it uses fickle third-party extension modules, for instance) you may want to do the cleanup in a simple parent process for more isolation.

If you aren't really worried, use the atexit module.

Thomas Wouters
I was not completely sure the destructor would be called either. Thanks for the clarification! It appears that atexit is what I need.
EmmEff
+1  A: 

That seems like a reasonable approach, and more straightforward and reliable than a destructor on a singleton class. You might also look at the "atexit" module. (Pronounced "at exit", not "a tex it" or something like that. I confused that for a long while.)

keturn
+2  A: 

if you use classes, you should free the resources they allocate in their destructors instead, of course. Use the try: on entire application just if you want to free resources that aren't already liberated by your classes' destructors.

And instead of using a catch-all except:, you should use the following block:

try:
    main()
finally:
    cleanup()

That will ensure cleanup in a more pythonic way.

nosklo
A: 

Consider writing a context manager and using the with statement.

Ignacio Vazquez-Abrams