How do I terminate a script? - python

How do I exit a script early, like the die() command in PHP?

import sys
sys.exit()
details from the sys module documentation:
sys.exit([arg])
Exit from Python. This is implemented by raising the
SystemExit exception, so cleanup actions specified by finally clauses
of try statements are honored, and it is possible to intercept the
exit attempt at an outer level.
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. If another type of object
is passed, None is equivalent to passing zero, and any other object is
printed to stderr and results in an exit code of 1. In particular,
sys.exit("some error message") is a quick way to exit a program when
an error occurs.
Since exit() ultimately “only” raises an exception, it will only exit
the process when called from the main thread, and the exception is not
intercepted.
Note that this is the 'nice' way to exit. #glyphtwistedmatrix below points out that if you want a 'hard exit', you can use os._exit(*errorcode*), though it's likely os-specific to some extent (it might not take an errorcode under windows, for example), and it definitely is less friendly since it doesn't let the interpreter do any cleanup before the process dies. On the other hand, it does kill the entire process, including all running threads, while sys.exit() (as it says in the docs) only exits if called from the main thread, with no other threads running.

A simple way to terminate a Python script early is to use the built-in quit() function. There is no need to import any library, and it is efficient and simple.
Example:
#do stuff
if this == that:
quit()

Another way is:
raise SystemExit

You can also use simply exit().
Keep in mind that sys.exit(), exit(), quit(), and os._exit(0) kill the Python interpreter. Therefore, if it appears in a script called from another script by execfile(), it stops execution of both scripts.
See "Stop execution of a script called with execfile" to avoid this.

While you should generally prefer sys.exit because it is more "friendly" to other code, all it actually does is raise an exception.
If you are sure that you need to exit a process immediately, and you might be inside of some exception handler which would catch SystemExit, there is another function - os._exit - which terminates immediately at the C level and does not perform any of the normal tear-down of the interpreter; for example, hooks registered with the "atexit" module are not executed.

I've just found out that when writing a multithreadded app, raise SystemExit and sys.exit() both kills only the running thread. On the other hand, os._exit() exits the whole process. This was discussed in "Why does sys.exit() not exit when called inside a thread in Python?".
The example below has 2 threads. Kenny and Cartman. Cartman is supposed to live forever, but Kenny is called recursively and should die after 3 seconds. (recursive calling is not the best way, but I had other reasons)
If we also want Cartman to die when Kenny dies, Kenny should go away with os._exit, otherwise, only Kenny will die and Cartman will live forever.
import threading
import time
import sys
import os
def kenny(num=0):
if num > 3:
# print("Kenny dies now...")
# raise SystemExit #Kenny will die, but Cartman will live forever
# sys.exit(1) #Same as above
print("Kenny dies and also kills Cartman!")
os._exit(1)
while True:
print("Kenny lives: {0}".format(num))
time.sleep(1)
num += 1
kenny(num)
def cartman():
i = 0
while True:
print("Cartman lives: {0}".format(i))
i += 1
time.sleep(1)
if __name__ == '__main__':
daemon_kenny = threading.Thread(name='kenny', target=kenny)
daemon_cartman = threading.Thread(name='cartman', target=cartman)
daemon_kenny.setDaemon(True)
daemon_cartman.setDaemon(True)
daemon_kenny.start()
daemon_cartman.start()
daemon_kenny.join()
daemon_cartman.join()

from sys import exit
exit()
As a parameter you can pass an exit code, which will be returned to OS. Default is 0.

I'm a total novice but surely this is cleaner and more controlled
def main():
try:
Answer = 1/0
print Answer
except:
print 'Program terminated'
return
print 'You wont see this'
if __name__ == '__main__':
main()
...
Program terminated
than
import sys
def main():
try:
Answer = 1/0
print Answer
except:
print 'Program terminated'
sys.exit()
print 'You wont see this'
if __name__ == '__main__':
main()
...
Program terminated Traceback (most recent call last): File "Z:\Directory\testdieprogram.py", line 12, in
main() File "Z:\Directory\testdieprogram.py", line 8, in main
sys.exit() SystemExit
Edit
The point being that the program ends smoothly and peacefully, rather than "I'VE STOPPED !!!!"

Problem
In my practice, there was even a case when it was necessary to kill an entire multiprocessor application from one of those processes.
The following functions work well if your application uses the only main process. But no one of the following functions didn't work in my case as the application had many other alive processes.
quit()
exit(0)
os._exit(0)
sys.exit(0)
os.kill(os.getppid(), 9) - where os.getppid() is the pid of parent process
The last one killed the main process and itself but the rest processes were still alive.
Solution
I had to kill it by external command and finally found the solution using pkill.
import os
# This can be called even in process worker and will kill
# whole application included correlated processes as well
os.system(f"pkill -f {os.path.basename(__file__)}")

In Python 3.5, I tried to incorporate similar code without use of modules (e.g. sys, Biopy) other than what's built-in to stop the script and print an error message to my users. Here's my example:
## My example:
if "ATG" in my_DNA:
## <Do something & proceed...>
else:
print("Start codon is missing! Check your DNA sequence!")
exit() ## as most folks said above
Later on, I found it is more succinct to just throw an error:
## My example revised:
if "ATG" in my_DNA:
## <Do something & proceed...>
else:
raise ValueError("Start codon is missing! Check your DNA sequence!")

My two cents.
Python 3.8.1, Windows 10, 64-bit.
sys.exit() does not work directly for me.
I have several nexted loops.
First I declare a boolean variable, which I call immediateExit.
So, in the beginning of the program code I write:
immediateExit = False
Then, starting from the most inner (nested) loop exception, I write:
immediateExit = True
sys.exit('CSV file corrupted 0.')
Then I go into the immediate continuation of the outer loop, and before anything else being executed by the code, I write:
if immediateExit:
sys.exit('CSV file corrupted 1.')
Depending on the complexity, sometimes the above statement needs to be repeated also in except sections, etc.
if immediateExit:
sys.exit('CSV file corrupted 1.5.')
The custom message is for my personal debugging, as well, as the numbers are for the same purpose - to see where the script really exits.
'CSV file corrupted 1.5.'
In my particular case I am processing a CSV file, which I do not want the software to touch, if the software detects it is corrupted. Therefore for me it is very important to exit the whole Python script immediately after detecting the possible corruption.
And following the gradual sys.exit-ing from all the loops I manage to do it.
Full code: (some changes were needed because it is proprietory code for internal tasks):
immediateExit = False
start_date = '1994.01.01'
end_date = '1994.01.04'
resumedDate = end_date
end_date_in_working_days = False
while not end_date_in_working_days:
try:
end_day_position = working_days.index(end_date)
end_date_in_working_days = True
except ValueError: # try statement from end_date in workdays check
print(current_date_and_time())
end_date = input('>> {} is not in the list of working days. Change the date (YYYY.MM.DD): '.format(end_date))
print('New end date: ', end_date, '\n')
continue
csv_filename = 'test.csv'
csv_headers = 'date,rate,brand\n' # not real headers, this is just for example
try:
with open(csv_filename, 'r') as file:
print('***\nOld file {} found. Resuming the file by re-processing the last date lines.\nThey shall be deleted and re-processed.\n***\n'.format(csv_filename))
last_line = file.readlines()[-1]
start_date = last_line.split(',')[0] # assigning the start date to be the last like date.
resumedDate = start_date
if last_line == csv_headers:
pass
elif start_date not in working_days:
print('***\n\n{} file might be corrupted. Erase or edit the file to continue.\n***'.format(csv_filename))
immediateExit = True
sys.exit('CSV file corrupted 0.')
else:
start_date = last_line.split(',')[0] # assigning the start date to be the last like date.
print('\nLast date:', start_date)
file.seek(0) # setting the cursor at the beginnning of the file
lines = file.readlines() # reading the file contents into a list
count = 0 # nr. of lines with last date
for line in lines: #cycling through the lines of the file
if line.split(',')[0] == start_date: # cycle for counting the lines with last date in it.
count = count + 1
if immediateExit:
sys.exit('CSV file corrupted 1.')
for iter in range(count): # removing the lines with last date
lines.pop()
print('\n{} lines removed from date: {} in {} file'.format(count, start_date, csv_filename))
if immediateExit:
sys.exit('CSV file corrupted 1.2.')
with open(csv_filename, 'w') as file:
print('\nFile', csv_filename, 'open for writing')
file.writelines(lines)
print('\nRemoving', count, 'lines from', csv_filename)
fileExists = True
except:
if immediateExit:
sys.exit('CSV file corrupted 1.5.')
with open(csv_filename, 'w') as file:
file.write(csv_headers)
fileExists = False
if immediateExit:
sys.exit('CSV file corrupted 2.')

Just put at the end of your code quit() and that should close a python script.

In Python 3.9, you can also use: raise SystemExit("Because I said so").

use exit and quit in .py files
and sys.exit for exe files

Related

How to terminate/killall a program in python

The first simple answer to the Linux equivalent killall(ProgramName)
The program is to be a toggle program. I can launch Firefox/program.
def tolaunch(program):
os.system("firefox")
When launched I wish to save the name of program launched, in array(simple to do), then launch the program(Firefox)/program.
Here the idea off the toggle come’s in, when Launched and I have finished my browsing, I wish to call the same program(mine), check the array for said program and exit Firefox/program, by running a simple command like killall(“Firefox”) but in Python code. I don’t want to write a long winded command/script, that first has to workout the ‘pid’.
I seem very close to the answer but cant find it.
Edit: people asked for code example | here is my code
# Toggler for macro key -|- many keys = one toggler program
import os
import sys
def startp(program):
# hard-coded
os.system("firefox")
def exitp(program):
# os.close(program)
sys.exit(program)
# Begin
# hard-coded : program start
startp("Firefox")
# loop while program/s active
# exitp("Firefox")
# exit(program) or program end
I tried to include some explanations in way off comments
What you are looking for is the sys.exit() command.
There are 4 functions that exit a program. These are the quit(), exit(), sys.exit() and os._exit(). They have almost same functionality thanks to the fact that they raise the SystemExit exception by which the Python interpreter exits and no stack traceback is printed on the screen.
Among the above four exit functions, sys.exit() is mostly preferred because the exit() and quit() functions cannot be used in production code while os._exit() is for special cases only when an immediate exit is required.
To demonstrate this behavior using the sys.exit() function:
import sys
i=0
while i in range(10):
i += 1
print(i)
if i == 5:
print('I will now exit')
sys.exit()
elif i > 5:
print('I will not run, program alredy exited :(')

Send flag to python program to exit, in its own time. Windows

I am writing a long-term prime search program, that can be closed and reopened with a system of writing out found primes to file. I do not want help with the algs, but I need a method of killing the program only when it gets to the end of the main loop i.e. it has fully found a prime. The relevant parts of code are below.
check = 7
def isprime(n):
#do...
while True:
if isprime(check):
print(check, "is prime")
else:
print(check, "isn't prime")
check += 2
This code will not work, but it is a good template as my question is not specific to my program. I want to break out of the main while True loop, only when at the end of it. The only solution I could think of, which is not practical at all, is at the end of while True I read in a file and if it is "stop" I break. However, I don't want to have to type into a file when I want to stop, and reading a file is a time-waster.
I am sorry if this question appears opinion based, but I tried my best.
Threading is a good option as suggested by others. However, you can have a lighter option of using a try/except catching a keyboard interrupt and using an end flag. If the kill signal is sent during the isprime() calculation, the current calculation for isprime() will be killed, check will not be incremented by 2, the except block will execute to switch the end flag to True, and then you will re-start the isprime calculation for the previous check until you are done, increment, then break. The advantage of this method is that it is lighter than having the overhead of creating a new thread (which is small compared to creating a new process) and that it is easier to debug than a multithreaded script. However, the multithreaded option is fine to debug if the code will not get much bigger and you won't be needing other threads as a part of the same script.
end = False
while True:
try:
if isprime(check):
print(check, "is prime")
else:
print(check, "isn't prime")
check += 2
if end:
break
except KeyboardInterrupt:
print('end signal received')
end = True
You can define a function to create a prime and another function to listen to KeyboardInterrupt signals as Ralf commented. In your prime function at the end do a
if not Keyboard_thread.is_alive():
break
This will have your code check that it has not been stopped only at the end of the cycle, thereby avoiding terminating your program mid calculation. Threading documentation is at https://docs.python.org/2/library/threading.html for more depth! essentially though you want to do something like
t = threading.Thread(target=your_function, args=[your_list_of_parameters](arguments are optional))
t.start()
Sorry if you already know threads, but it wasn't part of your post so I will assume you do not.
You can call t.join() to end your thread that is waiting for keyboard interrupts (specifying a timeout), or have your function come to an end by breaking. Doing so will then flag your other thread (the one checking if keyboard_thread.is_alive() that it should also break out of its loop. Note: threads only run until the end of the function you assign them, so for instance if your function is:
def new_function():
print("hey")
If you assign a thread to this function, the thread will print "hey" once and then terminate itself upon reaching the end of the function. Feel free to leave a comment if something I said is unclear!

Good way of closing a file

Let us say, we have the following code:
from sys import exit
def parseLine(l):
if '#' not in l:
print 'Invalid expresseion'
exit(1)
return l
with open('somefile.txt') as f:
for l in f:
print parseLine(l)
(Note that this is a demo code. The actual program is much more complex.)
Now, how do I know if I have safely closed all the open files when I exit from the program? At this point I am just assuming that the files have been closed. Currently my programs are working OK, but I want them to be robust and free of problems related to files not closed properly.
One of the chief benefits of the with block with files is that it will automatically close the file, even if there's an exception.
https://docs.python.org/2/tutorial/inputoutput.html#methods-of-file-objects
It's already closing properly, since you're using a with statement when you open the file. That'll automatically close the file when control leaves the with statement, even if there's an exception. This is usually considered the best way to ensure files are closed when they should be.
If you don't use a with statement or close the file yourself, there are a few built-in safeties and a few pitfalls.
First, in CPython, the file object's destructor will close the file when it gets garbage-collected. However, that isn't guaranteed to happen in other Python implementations, and even in CPython, it isn't guaranteed to happen promptly.
Second, when your program exits, the operating system will close any files the program left open. This means if you accidentally do something that makes the program never close its files (perhaps you had to issue a kill -9 or something else that prevents cleanup code from running), you don't have to reboot the machine or perform filesystem repair to make the file usable again. Relying on this as your usual means of closing files would be inadvisable, though.
If you're using a with block, you essentially have your open call inside of a try block and the close in a finally block. See https://docs.python.org/2/tutorial/inputoutput.html for more information from the official docs.
Since calling exit() actually raises the SystemExit exception, all code within finally blocks will be run before the program completely exits. Since this is the case, and since you're using with open(...) blocks, the file will be closed with any uncaught exception.
Below is your code (runnable/debuggable/steppable at http://python.dbgr.cc/s)
from sys import exit
def parseLine(l):
if '#' not in l:
print 'Invalid expresseion'
exit(1)
return l
with open('somefile.txt') as f:
for l in f:
print parseLine(l)
print("file is closed? %r" % f.closed)
Equivalent code without using the with open(...) block is shown below (runnable/debuggable at http://python.dbgr.cc/g):
from sys import exit
def parseLine(l):
if '#' not in l:
print 'Invalid expresseion'
exit(1)
return l
try:
f = open('somefile.txt')
for l in f:
print parseLine(l)
finally:
print("Closing open file!")
f.close()
print("file is closed? %r" % f.closed)

Is there a way to make py.test ignore SystemExit raised on a child process?

I'm testing a Python module which contains the following snippet of code.
r, w = os.pipe()
pid = os.fork()
if pid:
os.close(w) # use os.close() to close a file descriptor
r = os.fdopen(r) # turn r into a file object
# read serialized object from ``r`` and persists onto storage medium
self.ofs.put_stream(bucket, label, r, metadata)
os.waitpid(pid, 0) # make sure the child process gets cleaned up
else:
os.close(r)
w = os.fdopen(w, 'w')
# serialize object onto ``w``
pickle.dump(obj, w)
w.close()
sys.exit(0)
return result
All tests pass, but there's s difficulty in regards to sys.exit(0).
When sys.exit(0) executes, it raises SystemExit, which is intercepted by py.test and reported as an error in the console.
I don't understand in detail what py.test does internally, but looks like it goes ahead and ends up ignoring such event raised by the child process. In the end, all tests pass, which is good.
But I'd like to have a clean output in the console.
Is there a way to make py.test produce a clean output?
For your information:
Debian Jessie, kernel 3.12.6
Python 2.7.6
pytest 2.5.2
Thanks :)
( answering my own question )
You can terminate execution without provoking signals associated to these events.
So, instead of sys.exit(n), use os._exit(n), where n is the status code desired.
Example:
import os
os._exit(0)
credits:
Is there a way to prevent a SystemExit exception raised from sys.exit() from being caught?
def test_mytest():
try:
# code goes here
# like
# import my_packaage.__main__
# which can raise
# a SystemExit
except SystemExit:
pass
assert(True)
I found it here.
This is how I solve the problem with mock - with this approach, you can take advantage of all the cleanup sys.exit will do for us
#mock.patch('your.module.sys.exit')
def test_func(mock_sys_exit):
mock_sys_exit.side_effect = SystemExit("system is exiting")
with pytest.raises(SystemExit):
# run function that supposed to trigger SystemExit

Terminating a Python Program

What command do you use in python to terminate a program?
i.e. the equivalent of "end" in basic, or "quit" in BASH.
I see that "break" takes you out of a loop, and "quit" is all tied up with "class" stuff that I do not comprehend yet.
i tried
import sys
sys.exit()
but it will display following error :
Traceback (most recent call last):
File "C:\Documents and Settings\....\Desktop\current file_hand\Python_1.py", line 131, in <module>
sys.exit()
SystemExit
is there any solution for it .
sys.exit(error_code)
Error_code will be 0 for a normal exit, 1 or some other positive number for an exit due to an error of some kind, e.g. the user has entered the wrong parameters.
sys.exit() "is undefined on some architectures", (although it worked when I tried it on my Linux box!)
The official python docs explains this more fully.
It's an extremely good idea for all your programs and scripts to follow the return code convention; 0 for OK, something else for error, (normally 1)
For example, if you run a script which grabs some data out of a database; returning 0 and no output, means the database is perfectly fine there's just nothing in it (or nothing matching your query). returning 1 and no output means there is a fault with the database, the whole process should abort, because to continue would corrupt the other system too.
sys.exit() raises the SystemExit exception.
If you don't catch that exception the program ends.
Since you're getting that output, I'm not sure what is happening, but I guess that you're catching all exceptions and printing them yourself:
try:
...
except:
print exception somehow
raise
If that's the case, don't do that. catch Exception instead:
...
except Exception:
...
That way you won't catch things not meant to be catched (like SystemExit).
You should also consider alternatives to exiting directly. Often return works just as well if you wrap code in a function. (Better, in fact, because it avoids sys.exit() weirdness.)
def main():
...do something...
if something:
return # <----- return takes the place of exit
...do something else...
main()
sys.exit() #to exit the program
return #to exit from a function
import sys
sys.exit(0)
Try running a python interpreter out of your IDE. In my Windows installation the simple command line python.exe, both options work:
>>> import sys
>>> sys.exit()
or
>>> raise SystemExit
In your case, your error is likely that you have a bare except block that is catching the SystemExit exception, like this:
import sys
try:
sys.exit(return_code)
except:
pass
The correct way to fix your problem is to remove the except: portion, and instead just catch the Exceptions you expect to be possibly raised. For example:
try:
# Code which could raise exceptions
except (NameError, ValueError):
# Do something in case of NameError or ValueError, but
# ignore other exceptions (like SystemExit)
However, if you really wanted your program to exit, the following code will work:
import os
try:
os._exit(return_code)
except:
pass
This will exit even with the except: clause, as it just directly calls the C function of the same name which kills your process. This is not recommended unless you know what you are doing, since this will not call cleanup handlers or flush open IO buffers.
I met this problem on Windows where I needed to close ParaView (I could not use pvbatch or pvpython, because of OpenGL initialization, and sys.exit does not work)
Below is the specific solution for Windows.
# import os module
import os
# delete given process
os.system('wmic process where name="Process_Name" delete')
# for example
os.system('wmic process where name="paraview.exe" delete')
Source of this solution is here

Categories