exit is a helper for the interactive shell - sys.exit is intended for use in programs.
The
sitemodule (which is imported automatically during startup, except if the-Scommand-line option is given) adds several constants to the built-in namespace (e.g.exit). They are useful for the interactive interpreter shell and should not be used in programs.
Technically, they do mostly the same: raising SystemExit. sys.exit does so in sysmodule.c:
static PyObject *
sys_exit(PyObject *self, PyObject *args)
{
PyObject *exit_code = 0;
if (!PyArg_UnpackTuple(args, "exit", 0, 1, &exit_code))
return NULL;
/* Raise SystemExit so callers may catch it or clean up. */
PyErr_SetObject(PyExc_SystemExit, exit_code);
return NULL;
}
While exit is defined in site.py and _sitebuiltins.py, respectively.
class Quitter(object):
def __init__(self, name):
self.name = name
def __repr__(self):
return 'Use %s() or %s to exit' % (self.name, eof)
def __call__(self, code=None):
# Shells like IDLE catch the SystemExit, but listen when their
# stdin wrapper is closed.
try:
sys.stdin.close()
except:
pass
raise SystemExit(code)
__builtin__.quit = Quitter('quit')
__builtin__.exit = Quitter('exit')
Note that there is a third exit option, namely os._exit, which exits without calling cleanup handlers, flushing stdio buffers, etc. (and which should normally only be used in the child process after a fork()).
exit is a helper for the interactive shell - sys.exit is intended for use in programs.
The
sitemodule (which is imported automatically during startup, except if the-Scommand-line option is given) adds several constants to the built-in namespace (e.g.exit). They are useful for the interactive interpreter shell and should not be used in programs.
Technically, they do mostly the same: raising SystemExit. sys.exit does so in sysmodule.c:
static PyObject *
sys_exit(PyObject *self, PyObject *args)
{
PyObject *exit_code = 0;
if (!PyArg_UnpackTuple(args, "exit", 0, 1, &exit_code))
return NULL;
/* Raise SystemExit so callers may catch it or clean up. */
PyErr_SetObject(PyExc_SystemExit, exit_code);
return NULL;
}
While exit is defined in site.py and _sitebuiltins.py, respectively.
class Quitter(object):
def __init__(self, name):
self.name = name
def __repr__(self):
return 'Use %s() or %s to exit' % (self.name, eof)
def __call__(self, code=None):
# Shells like IDLE catch the SystemExit, but listen when their
# stdin wrapper is closed.
try:
sys.stdin.close()
except:
pass
raise SystemExit(code)
__builtin__.quit = Quitter('quit')
__builtin__.exit = Quitter('exit')
Note that there is a third exit option, namely os._exit, which exits without calling cleanup handlers, flushing stdio buffers, etc. (and which should normally only be used in the child process after a fork()).
If I use exit() in a code and run it in the shell, it shows a message asking whether I want to kill the program or not. It's really disturbing.
See here
But sys.exit() is better in this case. It closes the program and doesn't create any dialogue box.
Let's say you have a script that is a simple csv parser but the user enters an invalid filepath for the csv.
Is it better to exit the script with a print("wrong filepath") and then sys.exit(1) or by using raise SomeError("wrong filepath")?
From what I read sys.exit(1) raises an exception also, but it doesn't seem to print a traceback like using raise SomeError("wrong filepath") does. So you can just print the message you want the user to see and exit quietly.
If I were to distribute a script like this to public users. What's the better practice?
You're looking for calls to sys.exit(...) (exit(...) calls sys.exit(...)) in the script. The argument to that method is returned to the environment as the exit code.
It's fairly likely that the script is never calling the exit(...) method, and that 0 is the default exit code.
From the documentation for sys.exit:
The optional argument arg can be an integer giving the exit status (defaulting to zero), or another type of object. If it is an integer, zero is considered “successful termination” and any nonzero value is considered “abnormal termination” by shells and the like. Most systems require it to be in the range 0-127, and produce undefined results otherwise. Some systems have a convention for assigning specific meanings to specific exit codes, but these are generally underdeveloped; Unix programs generally use 2 for command line syntax errors and 1 for all other kind of errors.
One example where exit codes are used are in shell scripts. In Bash you can check the special variable $? for the last exit status:
me@mini:~$ python -c ""; echo $?
0
me@mini:~$ python -c "import sys; sys.exit(0)"; echo $?
0
me@mini:~$ python -c "import sys; sys.exit(43)"; echo $?
43
Personally I try to use the exit codes I find in /usr/include/asm-generic/errno.h (on a Linux system), but I don't know if this is the right thing to do.
This will call the function main() and when main finishes, it will exit giving the system the return code that is the result of main().
A simplified example where this might be used:
def main():
try:
doSomething()
return 0
except:
return 1
if __name__ == "__main__":
exit (main())
If an explicit return value is not given in main(), the default value of None will be returned. This produces the same system return code as explicitly specifying return 0. If main returns anything other than an integer or None a system return code of 1 will be produced.
If you execute a Python script directly, __name__ is set to "__main__", but if you import it from another script, it is not.
So in this case, the script is seeing if you're executing it directly. If it is, it calls the main() function to perform some work, and returns the return value of the main() function to the system via exit(). If the script is being imported from another module, it doesn't execute the main() function and simply provides the script's functions and classes to the importing script.
This is a common idiom in Python. It allows you to have scripts that are standalone programs, but can also be imported without trying to do work that the importing script doesn't want done.
sys.exit(-1) tells the program to quit. It basically just stops the python code from continuing execution. -1 is just the status code that is passed in. Generally 0 denotes successful execution, any other number (usually 1) means something broke.
The call sys.exit(n) tells the interpreter to stop the execution and return n to the OS. What this value is depends on the operating system.
For example on UNIX ($? is the last exit status):
$ python -c "import sys; sys.exit(-1)"
$ echo $?
255
This is because it treats the return value as an unsigned 8bit value (see here). On Windows the value would be an unsigned 32bit value (from here) and thus be 4294967295.
As you can see in the first link, the convention is to return 0 on a successful exit and a non-zero value otherwise. Sometimes you'll see that an application has a certain convention for its status codes.
For example the program wget has a section in its man page that tells you why an error occurred:
EXIT STATUS
Wget may return one of several error codes if it encounters problems.
0 No problems occurred.
1 Generic error code.
2 Parse error---for instance, when parsing command-line options, the .wgetrc or .netrc...
3 File I/O error.
4 Network failure.
5 SSL verification failure.
6 Username/password authentication failure.
7 Protocol errors.
8 Server issued an error response.
The convention of returning 0 on a success is very helpful for writing scripts:
$ if python -c "import sys; sys.exit(-1)"; then echo "Everything fine"; else echo "Not good"; fi
Not good
$ if python -c "import sys; sys.exit(0)"; then echo "Everything fine"; else echo "Not good"; fi
Everything fine
In most questions asking how to stop code the recommended answer is sys.exit() or raising an exception. Why is exit() not suggested given it is simpler, not requiring import sys, and it does the same thing underneath?
e.g. https://www.reddit.com/r/learnpython/comments/hv7phs/how_do_i_stop_a_code/?utm_medium=android_app&utm_source=share)
No practical difference, but there's another difference in your example code - print goes to standard out, but the exception text goes to standard error (which is probably what you want).
sys.exit(s) is just shorthand for raise SystemExit(s), as described in the former's docstring; try help(sys.exit). So, instead of either one of your example programs, you can do
sys.exit('Unable to open %s' % reference)