4

For a simple python script that doesn't start any threads or fork any processes, what's the difference between simply letting execution reach the end of the script and explicitly calling quit(), exit(), or sys.exit()?

i.e. what's the difference between

def main():
    # do some stuff
    print("Done doing stuff")

if __name__ == '__main__':
    main()

and

import sys

def main():
    # do some stuff
    print("Done doing stuff")
    # explicit exit
    sys.exit()

if __name__ == '__main__':
    main()

I'm asking this because I have been having some odd garbage collection issues on script termination (exceptions raised from __del__ apparently due to the order in which things get cleaned up) without the explicit exit() call, and adding an explicit exit() appears to correct those issues. Or at least none of those exceptions get printed after calling exit(), maybe they are simply being silenced.

alex.forencich
  • 1,355
  • 11
  • 16
  • From what I garner, the `sys.exit()` allows the 'finally' clause, wherein the clean-up functionality is built, of some try blocks to activate by raising an exception, thereby giving a "cleaner" exit. – Uvar Aug 10 '17 at 14:11
  • https://docs.python.org/3/library/sys.html#sys.exit "This is implemented by raising the SystemExit exception, so cleanup actions specified by finally clauses of try statements are honored". Another interesting note is the one on the buffering errors caught while cleaning up, which cause the exit code to become 120 – BoboDarph Aug 10 '17 at 14:15
  • I believe this should answer your questions: https://stackoverflow.com/questions/19747371/python-exit-commands-why-so-many-and-when-should-each-be-used – Brandon C Aug 10 '17 at 14:16
  • So if I really want to exit properly, I have to catch all exceptions, manually print a stack trace, and then call `sys.exit()`? – alex.forencich Aug 10 '17 at 14:22

1 Answers1

0

In the case you have posted, there is no difference. But the are cases in which you may want to terminate your program without waiting for it to finish.

A banal example:

try:
    ...
except KeyboardInterrupt:
    x = input('Sure you want to exit? y/n')
    if x == 'y':
        quit()
    else:
        pass
alec_djinn
  • 10,104
  • 8
  • 46
  • 71
  • There is some difference, somewhere because I am getting exceptions in `__del__` in some instantiated objects due to the order in which python is cleaning things up when I *don't* explicitly call `exit()` or `sys.exit()` – alex.forencich Aug 10 '17 at 14:28
  • Can you post the actual code then? It's hard to see what can be the difference from your snippet. – alec_djinn Aug 10 '17 at 14:29
  • I don't have a good, portable minimal example right now as it involves python-ivi, pyvisa, NI-VISA, and open connections to actual test equipment. – alex.forencich Aug 10 '17 at 14:31
  • The exceptions that I am seeing are due to one object (pyvisa resource manager instance) being deleted before another object (pyvisa resource instance)...but the problem is that I have no idea why python is deleting the resource manager instance first when the resource instance has a reference to the resource manager. Explicitly calling `exit()` seems to make this work properly, so to debug this further I need to know more about what the difference is between calling `exit()` and not calling `exit()` as this seems to have some effect on how python cleans up. – alex.forencich Aug 10 '17 at 14:39