Shells, CI pipelines and schedulers decide success or failure purely from a process's exit code.
A process reports success or failure to whoever started it with an exit code: 0 means success, anything from 1 to 255 means failure. Shell &&, set -e, CI jobs and cron alerts all depend on it.
sys.exit(arg) ends the program:
sys.exit()orsys.exit(0): success.sys.exit(2): exit with code 2 (by convention, 2 means a usage error).sys.exit("error: config missing"): prints the message to stderr and exits with code 1.
An uncaught exception also exits with code 1 after printing the traceback.
sys.exit does not stop the interpreter immediately. It raises the SystemExit exception. That means finally blocks and with statements still run their cleanup, and atexit handlers run afterwards. It also means a bare except: or except BaseException: will swallow it; except Exception: does not, because SystemExit derives directly from BaseException.
In a script, the common shape is:
if __name__ == "__main__":
sys.exit(main())where main() returns an int. Prefer sys.exit over the built-in exit()/quit(), which are meant for the interactive prompt. os._exit(code) exits instantly without any cleanup and is only for special cases such as forked children.
Example
import subprocess
import sys
def code_of(src):
return subprocess.run([sys.executable, "-c", src],
capture_output=True, text=True)
print(code_of("import sys; sys.exit()").returncode) # 0
print(code_of("import sys; sys.exit(3)").returncode) # 3
r = code_of("import sys; sys.exit('bad config')")
print(r.returncode, r.stderr.strip()) # 1 bad config
print(code_of("1 / 0").returncode) # 1
try:
sys.exit(5)
except SystemExit as e: # it is just an exception
print("caught", e.code) # caught 5
finally:
print("cleanup runs") # cleanup runsRemember
- Exit code 0 means success; non-zero means failure
sys.exit(n)raises SystemExit, sofinallyandwithcleanup still runsys.exit('msg')prints to stderr and exits with code 1
Watch out for
- Wrapping code in
except BaseException:or a bareexcept:that swallows SystemExit, so the program never exits.