I’m starting finishing off my new simple app and because Python isn’t my main programming language I’m struggling a lot. I would like to add a function which would kill everything - every service in the app, after clicking an exit button. (So maybe with a global variable?)
I want to do it as simple as possible. I was wondering if there is anything similar to isServerOn or so.
What I have so far is just this code below and if there would be a chance to add just one or few lines then it would be the best. Thank you all so much!!
import sys
def quit()
sys.exit()
To stop a python script use the keyboard: Ctrl + C
To stop it using code you can use these sections (Python 3) :
raise SystemExit
you can also use:
import sys
sys.exit()
or:
exit()
or:
import os
os._exit(0)
After a run, the user is asked whether he wants to end the programme [with sys.exit()] or restart it [os.system('main.py')].
If he restarts the programme, the programme will run through until he can decide again whether to restart or exit.
If the user then wants to end the programme, however, this is not possible, the programme is restarted anyway.
Also quit() or exit() do not work.
This is the prompt that asks the user to restart or quit:
while (res := input("Do you want to play again [1] oder exit[2]?\n").lower()) not in {"1", "2"}:
pass
if res == "1":
os.system('main.py')
else:
end_game = True # Stops the loop, but is not necessary
print("Sys.exit game")
sys.exit(0)
When I use subprocess.call(sys.executable + ' "' + os.path.realpath(__file__) + '"'),
exiting the program works, but the program is not really restarted [variables set to 0 at the beginning are not at 0].
Small note, the reboot will restart another py file (main.py), which is the main file, with the following content:
class main:
game_logic()
if __name__ == '__main__':
main()
game_logic() is the function from the other Py file in which the query for restarting and exiting is.
import os
import sys
while (res := input("Do you want to play again [1] oder exit[2]?\n").lower()) not in {"1", "2"}:
pass
if res == "1":
python = sys.executable
os.execl(python, python, * sys.argv)
else:
end_game = True # Stops the loop, but is not necessary
print("Sys.exit game")
sys.exit(0)
and
class main:
game_logic()
if __name__ == '__main__':
main()
The example above should work for you. You should use os.execl(...) instead of os.system(...). The last one creates new processes recursively and could cause an out of memory problem. You shouldn't create new processes, instead you want to replace the current process with a new one. This could be done with execl() or other calls from exec family.
To understand it properly, you may want to look here. It referes to C language, but it is kind of the same, because Python is wrapping around native calls.
Like all of the exec functions, execv replaces the calling process
image with a new process image. This has the effect of running a new
progam with the process ID of the calling process. Note that a new
process is not started; the new process image simply overlays the
original process image. The execv function is most commonly used to
overlay a process image that has been created by a call to the fork
function.
I have been able to answer this question myself in the meantime.
I have done the following:
game_logic() is started via another py file (main.py).
At the restart which is executed within the game_logic() with os.system('main.py'), the current py file containing game_logic() is not terminated.
So if the main.py file is restarted, I have the file containing the game_logic() terminate afterwards.
It looks like this:
import os
import sys
while (res := input("Do you want to play again [1] oder exit[2]?\n").lower()) not in {"1", "2"}:
pass
if res == "1":
os.system('main.py')
exit()
else:
exit()
I need to print out sentence "Hello World" every 10 seconds. However, if the user either 'c' or 'Enter', the program should stop printing the sentence and prompt the user to provide with the another sentence. The user-provided sentence is checked and if the sentence contains any digits, a message shows up: "cannot contain digits". Otherwise a message shows up: "correct sentence". After displaying either of the messages, the program continues printing "Hello World".
Here is the code I have strated with. Any hints on how to continue further would be greatly appreciated.
Thanks!
import threading
def looping():
threading.Timer(10.0, looping).start()
print("Hello World!")
looping()
From my understanding of your assignment's instructions, it looks like you're on the right track with using a timer to print "Hello World"! I'd like to upvote Irmen de Jong's comment on your question with regard to the statement "threads and console input/output don't work nicely together", since I've experienced this myself in C programming.
Once you have the timer going, the text it prints to the screen shouldn't have an effect on responding to keyboard input. If it's really required to respond directly to a keypress of 'c' (not followed by 'Enter', as one would normally have to do when reading input from the keyboard with input()), I recommend following one of the solutions in Python method for reading keypress? to figure out how you would like to implement that.
EDIT: Implementing a solution using a thread-based timer is a bit more tricky than I thought.
As you may have found in your research on this problem, the threading.Timer object has both start() and stop() methods that you can use to control the execution of individual thread timers if you've saved a reference to the timer in a variable (e.g. doing my_timer = threading.Timer(10.0, looping) then calling my_timer.start() to start the timer). If you do this, you may be able to call my_timer.stop() to pause the looping, provided you've kept a proper reference to the current timer instance that you need to stop at that point in time.
To make things a bit easier, I chose to create a global variable PAUSE_LOOPING that, when set to False, will stop a new timer instance from being started when looping is called, thereby halting all further repetitions of the function until PAUSE_LOOPING is set back to True and looping() is called again:
import threading
from msvcrt import getch
PAUSE_LOOPING = False
def looping():
global PAUSE_LOOPING
if not PAUSE_LOOPING:
threading.Timer(10.0, looping).start()
print("Hello World!")
looping()
while True:
# key = ord(getch())
# if key == 13: # Enter
# PAUSE_LOOPING = True
input_string = input()
if input_string == "":
PAUSE_LOOPING = True
else:
PAUSE_LOOPING = False
looping()
Commented out in the last code block is one way to grab a key press directly (without needing to press the 'Enter' key as is required by input()) taken from the stackoverflow question I linked to earlier in my answer. This should work as long as you're using Python for Windows (so you have the MS VC++ runtime library msvcrt installed), but to make the script stop when pressing 'Enter' you can use the standard input() function. In my example, typing any other string of characters before pressing 'Enter' will resume looping after it's been paused.
NOTE: Beware of using Python's IDLE to run this code. It won't work. Instead, you must run it from the command line.
I have a GUI program which should also be controllable via CLI (for monitoring). The CLI is implemented in a while loop using raw_input.
If I quit the program via a GUI close button, it hangs in raw_input and does not quit until it gets an input.
How can I immediately abort raw_input without entering an input?
I run it on WinXP but I want it to be platform independent, it should also work within Eclipse since it is a developer tool. Python version is 2.6.
I searched stackoverflow for hours and I know there are many answers to that topic, but is there really no platform independent solution to have a non-blocking CLI reader?
If not, what would be the best way to overcome this problem?
Thanks
That's not maybe the best solution but you could use the thread module which has a function thread.interrupt_main(). So can run two thread : one with your raw_input method and one which can give the interruption signal. The upper level thread raise a KeyboardInterrupt exception.
import thread
import time
def main():
try:
m = thread.start_new_thread(killable_input, tuple())
while 1:
time.sleep(0.1)
except KeyboardInterrupt:
print "exception"
def killable_input():
w = thread.start_new_thread(normal_input, tuple())
i = thread.start_new_thread(wait_sometime, tuple())
def normal_input():
s = raw_input("input:")
def wait_sometime():
time.sleep(4) # or any other condition to kill the thread
print "too slow, killing imput"
thread.interrupt_main()
if __name__ == '__main__':
main()
Depending on what GUI toolkit you're using, find a way to hook up an event listener to the close window action and make it call win32api.TerminateProcess(-1, 0).
For reference, on Linux calling sys.exit() works.
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