Difference between exit() and sys.exit() in Python - python

In Python, there are two similarly-named functions, exit() and sys.exit(). What's the difference and when should I use one over the other?

exit is a helper for the interactive shell - sys.exit is intended for use in programs.
The site module (which is imported automatically during startup, except if the -S command-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.

Solution, Origins, Differences & Speed
Why do we need the exit() /
sys.exit() commands?
Usually, the code runs through the lines until the end and the program exists automatically.
Occasionally, we would like to ask the program to close before the full cycle run.
An example case is when you implement authentication and a user fails to authenticate, in some cases you would like to exit the program.
The exit()
Exits Python.
Maybe you didn't know this, but it's a synonym of quit() and was added after quit() to make python more user friendly.
Designed to work with interactive shells.
Usage:
Use the built-in exit() out of the box, as is, without importing any library.
Just type this:
exit()
Execution Time: 0.03s
Pros:
Faster to use (built-in)
Works both with python 2.x and python 3.x
Fast
Can be used exactly like sys.exit() (with the exception)
Cons:
No exception message
The sys.exit()
Exits Python and raising the SystemExit exception (requires an import).
Designed to work inside programs.
Usage:
import sys
sys.exit()
Execution Time (of just the import and sys.exit()): 0.07s
Or you can use a message for the SystemExit exception:
Added finally block to illustrate code cleanup clause. Inspired by #Nairum.
import sys
try:
sys.exit("This is an exit!")
except SystemExit as error:
print(error)
finally:
print("Preforming cleanup in 3, 2, 1..")
# Do code cleanup on exit
Output:
This is an exit!
Preforming cleanup in 3, 2, 1..
Pros:
Triggers SystemExit exception
You can use an exception message
Closes without a dialog
Utilizes finally clause of try
Works both with python 2.x and python 3.x
Cons:
Needs an import
Slower by 57.1% than exit()
Conclusion:
If you don't need an exception with an optional message, then use exit(), this is faster and built-in.
If you require more functionality of an exception with an optional message, use sys.exit().
In the code examples I am using Python 3.x

Related

Catching Keyboard Interrupt with Raw Input

I have a bit of python code to to try and make raw_input catch keyboard interrupts. If I run the code in this function it works perfectly fine. But if I run it in my program, the print statement is never made, indicating that the keyboard interrupt is not caught. The program attempts to exit and fails until it escalates to SIGKILL, which of course works fine. My guess is somewhere else the keyboard interrupt is being caught, preventing the exception from running at all. My question is, where would such an interrupt likely occur, and how can I prevent it from blocking this one. My plan has been to add a slight delay between the program catching a keyboard interrupt and killing itself to give excepting here a moment to catch.
Any ideas appreciated
Thanks!
import sys
def interruptable_input(text=''):
'''Takes raw input, but accepts keyboard interrupt'''
try:
return raw_input(text)
except KeyboardInterrupt:
print "Interrupted by user"
sys.exit()
I have narrowed it down to the following:
import sys
text=''
try:
print raw_input(text)
except KeyboardInterrupt:
print "Interrupted by user"
sys.exit()
Which works perfectly when i run it on the command line using python 2.7.
It lets me type an input on the console and when I hit ctrl+c it prints intterupted by user
Edit:
I misread your question at first, however when i use the method from your example and call it from another method the result is the same
I have determined the reason for my issue was another interrupt handler killing the script before the KeyboardInterrupt was hit. I solved it by setting my own interrupt handler for signal.SIGINT like so:
import sys
import signal
signal.signal(signal.SIGINT, signal_term_handler)
def signal_term_handler(signal, frame):
'''Handles KeyboardInterrupts to ensure smooth exit'''
rospy.logerr('User Keyboard interrupt')
sys.exit(0)
it's slightly less direct but it get's the job done. Now raw_input() will simply die when told to.

How to catch exception from a system() command in python

I have a system() command and I want to catch the exception it may generate. The code that I have is:
def test():
filename = "test.txt"
try:
cmd = "cp /Users/user1/Desktop/Test_Folder/"+filename+" /Users/user1/Desktop/"
output = system(cmd)
except:
print 'In the except'
traceback.print_exc()
sys.exit(1)
if __name__ == '__main__':
test()
When I execute the above code and say the file that I want to copy is not present then the error is not caught and the code does not enter the except section. How can I catch such errors generated by system() commands?
Note: The above system() command is just an example. There are multiple such system() commands and each of them vary from one another
The system() command doesn't throw an exception on failure; it will simply return the exit status code of the application. If you want an exception thrown on failure, use subprocess.check_call, instead. (And, in general, using the subprocess module is superior in that it gives you greater control over the invocation as well as the ability to redirect the subprocess's standard input/output).
Note, though, that if most of the operations you are doing are simple filesystem operations like copying files from one location to another, that there are Python functions that do the equivalent. For example, shutil provides the ability to copy files from one location to another. Where there are Python functions to do the task, it is generally better to use those rather than invoke a sub process to do it (especially since the Python-provided methods may be able to do it more efficiently without forking a process, and the Python versions will also be more robust to cross-platform considerations).

Python curses dilemma

I'm playing around a little with Python and curses.
When I run
import time
import curses
def main():
curses.initscr()
curses.cbreak()
for i in range(3):
time.sleep(1)
curses.flash()
pass
print( "Hello World" )
curses.endwin()
if __name__ == '__main__':
main()
if I wait all the way through, curses.endwin() gets called so everything works out fine.
However, if I cut it short with Ctrl-C, curses.endwin() never gets called so it screws up my terminal session.
What is the proper way to handle this situation? How can I make sure that no matter how I try to end/interrupt the program (e.g. Ctrl-C, Ctrl-Z), it doesn't mess up the terminal?
I believe you are looking for curses.wrapper
See http://docs.python.org/dev/library/curses.html#curses.wrapper
It will do curses.cbreak(), curses.noecho() and curses_screen.keypad(1) on init and reverse them on exit, even if the exit was an exception.
Your program goes as a function to the wrapper, example:
def main(screen):
"""screen is a curses screen passed from the wrapper"""
...
if __name__ == '__main__':
curses.wrapper(main)
You could do this:
def main():
curses.initscr()
try:
curses.cbreak()
for i in range(3):
time.sleep(1)
curses.flash()
pass
print( "Hello World" )
finally:
curses.endwin()
Or more nicely, make a context wrapper:
class CursesWindow(object):
def __enter__(self):
curses.initscr()
def __exit__(self):
curses.endwin()
def main():
with CursesWindow():
curses.cbreak()
for i in range(3):
time.sleep(1)
curses.flash()
pass
print( "Hello World" )
My advice: For testing purposes, call your script using a simple wrapper shell script; have the shell script perform a reset command to bring your terminal settings back into a usable state:
#!/bin/sh
eval "$#"
stty -sane
reset
... call that as run.sh and be happy. This should run your command almost exactly as your shell would if you entered the arguments as a command (more exactly if you wrap the arguments in hard quotes).
To ensure that your program will leave the terminal in a robust state, in the the face of uncaught exceptions and abnormal terminations ... either use the curses.wrapper() method to call your top level entry point (probably main() or whatever main_curses_ui() you choose to implement) or wrap your code in your own sequence of curses.* methods to restore cursor visibility, restore "cbreak" (canonical/cooked input) mode, restore the normal "echo" settings and whatever else you may have mucked with.
You can also use the Python: atexit Handlers to register all your clean-up actions. But there might still be cases where your code doesn't get called --- some sorts of non-catchable signals and any situation where os._exit() is invoked.
My little shell script wrapper should be fairly robust even in those cases.
You can:
wrap your code in a try/finally block that calls curses.endwin()
capture the interrupt signal specifically via the signal library
use the atexit library.
The first option is probably the simplest for a basic case (if you're not running much code).
The second option is the most specific, if you want to do something special for Ctrl+C.
The last option is the most robust if you always want to do certain shutdown actions, no matter how your program is ending.
You need to capture the signal and run endwin() during the capture.
For info on this, look at this SO answer: How do I capture SIGINT in Python?

Exit to command line in Python

I have a script that I want to exit early under some condition:
if not "id" in dir():
print "id not set, cannot continue"
# exit here!
# otherwise continue with the rest of the script...
print "alright..."
[ more code ]
I run this script using execfile("foo.py") from the Python interactive prompt and I would like the script to exit going back to interactive interpreter. How do I do this? If I use sys.exit(), the Python interpreter exits completely.
In the interactive interpreter; catch SystemExit raised by sys.exit and ignore it:
try:
execfile("mymodule.py")
except SystemExit:
pass
Put your code block in a method and return from that method, like such:
def do_the_thing():
if not "id" in dir():
print "id not set, cannot continue"
return
# exit here!
# otherwise continue with the rest of the script...
print "alright..."
# [ more code ]
# Call the method
do_the_thing()
Also, unless there is a good reason to use execfile(), this method should probably be put in a module, where it can be called from another Python script by importing it:
import mymodule
mymodule.do_the_thing()
I'm a little obsessed with ipython for interactive work but check out the tutorial on shell embedding for a more robust solution than this one (which is your most direct route).
Instead of using execfile, you should make the script importable (name=='main protection, seperated into functions, etc.), and then call the functions from the interpreter.

How do I abort the execution of a Python script? [duplicate]

This question already has answers here:
How do I terminate a script?
(14 answers)
Closed 3 years ago.
I have a simple Python script that I want to stop executing if a condition is met.
For example:
done = True
if done:
# quit/stop/exit
else:
# do other stuff
Essentially, I am looking for something that behaves equivalently to the 'return' keyword in the body of a function which allows the flow of the code to exit the function and not execute the remaining code.
To exit a script you can use,
import sys
sys.exit()
You can also provide an exit status value, usually an integer.
import sys
sys.exit(0)
Exits with zero, which is generally interpreted as success. Non-zero codes are usually treated as errors. The default is to exit with zero.
import sys
sys.exit("aa! errors!")
Prints "aa! errors!" and exits with a status code of 1.
There is also an _exit() function in the os module. The sys.exit() function raises a SystemExit exception to exit the program, so try statements and cleanup code can execute. The os._exit() version doesn't do this. It just ends the program without doing any cleanup or flushing output buffers, so it shouldn't normally be used.
The Python docs indicate that os._exit() is the normal way to end a child process created with a call to os.fork(), so it does have a use in certain circumstances.
You could put the body of your script into a function and then you could return from that function.
def main():
done = True
if done:
return
# quit/stop/exit
else:
# do other stuff
if __name__ == "__main__":
#Run as main program
main()
import sys
sys.exit()
You can either use:
import sys
sys.exit(...)
or:
raise SystemExit(...)
The optional parameter can be an exit code or an error message. Both methods are identical. I used to prefer sys.exit, but I've lately switched to raising SystemExit, because it seems to stand out better among the rest of the code (due to the raise keyword).
Try
sys.exit("message")
It is like the perl
die("message")
if this is what you are looking for. It terminates the execution of the script even it is called from an imported module / def /function
exit() should do the trick
exit() should do it.
If the entire program should stop use sys.exit() otherwise just use an empty return.

Categories