I've searched this topic to no avail for hours.
Is it possible to do something along the lines of:
try:
input_var = input('> ')
except KeyboardInterrupt:
print("This will not work.")
But when I try this and do CTRL-C, it just does nothing.
Is there any other way to achieve this?
Using Windows 10, Python 3.5.2, and Powershell
Note: I am not using the input_var for printing, I am doing 3 if/elif/else statements based around it.
It sounds like you would be interested in the signal module.
This Answer demonstrates how to use the signal module to capture Ctrl+C, or SIGINT.
For your use case, something along the lines of the following would work :
#!/usr/local/bin/python3
import signal
def signal_handler(signal, frame):
raise KeyboardInterrupt('SIGINT received')
signal.signal(signal.SIGINT, signal_handler)
try :
input_var = input('> ')
except KeyboardInterrupt :
print("CTRL+C Pressed!")
Related
I've seen people suggesting sys.exit() in Python.
My question is that, is there any other way to exit the execution of current script, I mean termination, with an error.
Something like this:
sys.exit("You can not have three process at the same time.")
Currently my solution would be:
print("You can not have three process at the same time.")
sys.exit()
Calling sys.exit with a string will work. The docs mention this use explicitly:
In particular, sys.exit("some error message") is a quick way to exit a program when an error occurs.
There are 3 approaches, the first as lvc mentioned is using sys.exit
sys.exit('My error message')
The second way is using print, print can write almost anything including an error message
print >>sys.stderr, "fatal error" # Python 2.x
print("fatal error", file=sys.stderr) # Python 3.x
The third way is to rise an exception which I don't like because it can be try-catch
raise SystemExit('error in code want to exit')
it can be ignored like this
try:
raise SystemExit('error in code want to exit')
except:
print("program is still open")
You can also raise an error like this:
raise SystemExit('Error: 3 processes cannot run simultaneously.')
One advantage of this approach is that you don't have to import the Python sys module. This works on Linux with Python 3 and Python 2. I have not tested it on Windows or Mac OS.
You have to use import sys first
Then use sys.exit("your custom error message")
I made a program in Idle that says:
for trial in range(3):
if input('Password:') == 'password':
break
else:
# didn't find password after 3 attempts
**I need a stop program here**
print ("Welcome in")
Remember, this is in Idle, so I need program for Idle, not CMD. I also am using Python 3.2, if that helps.
A much nicer way to do this IMHO would be to put your program into a function and return when you want it to stop. Then just call the function to run your program.
def main():
for trial in range(3):
if input('Password:') == 'password':
break
else:
return
print ("Welcome in")
main()
use sys.exit() or raise SystemExit
import sys
for trial in range(3):
if input('Password:') == 'password':
break
else:
sys.exit()
print ("Welcome in"))
Edit:
To end it silently wrap it in a try-except block:
try:
import sys
for trial in range(1):
if raw_input('Password:') == 'password':
break
else:
raise SystemExit #or just sys.exit()
print ("Welcome in")
except SystemExit:
pass #when the program throws SysExit do nothing here,i.e end silently
I'm unsure what you mean by "in IDLE" vs "in CMD". A Python shell launched by IDLE should be able to be terminated the same way as a Python shell launched from the commandline.
Also, the tabs in your example appear to be wrong: everything below for... and above print... should be indented.
On to your question: are you asking for a command that terminates your script at that point? If so, adding the two lines from sys import exit and then calling exit() should do the trick, though it will raise a SystemExit exception. If you don't like that, you can add a pass handler for the SystemExit exception type at the outer layer of your program.
sys.exit can exit a program at any time.
I tried sys.exit() and it highlights 'sys' as INVALID SYNTAX.
It might be something to do with how I'm doing it, but if that's the case, then IDK then.
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.
Is there some way in Python to capture KeyboardInterrupt event without putting all the code inside a try-except statement?
I want to cleanly exit without trace if user presses Ctrl+C.
Yes, you can install an interrupt handler using the module signal, and wait forever using a threading.Event:
import signal
import sys
import time
import threading
def signal_handler(signal, frame):
print('You pressed Ctrl+C!')
sys.exit(0)
signal.signal(signal.SIGINT, signal_handler)
print('Press Ctrl+C')
forever = threading.Event()
forever.wait()
If all you want is to not show the traceback, make your code like this:
## all your app logic here
def main():
## whatever your app does.
if __name__ == "__main__":
try:
main()
except KeyboardInterrupt:
# do nothing here
pass
(Yes, I know that this doesn't directly answer the question, but it's not really clear why needing a try/except block is objectionable -- maybe this makes it less annoying to the OP)
An alternative to setting your own signal handler is to use a context-manager to catch the exception and ignore it:
>>> class CleanExit(object):
... def __enter__(self):
... return self
... def __exit__(self, exc_type, exc_value, exc_tb):
... if exc_type is KeyboardInterrupt:
... return True
... return exc_type is None
...
>>> with CleanExit():
... input() #just to test it
...
>>>
This removes the try-except block while preserving some explicit mention of what is going on.
This also allows you to ignore the interrupt only in some portions of your code without having to set and reset again the signal handlers everytime.
I know this is an old question but I came here first and then discovered the atexit module. I do not know about its cross-platform track record or a full list of caveats yet, but so far it is exactly what I was looking for in trying to handle post-KeyboardInterrupt cleanup on Linux. Just wanted to throw in another way of approaching the problem.
I want to do post-exit clean-up in the context of Fabric operations, so wrapping everything in try/except wasn't an option for me either. I feel like atexit may be a good fit in such a situation, where your code is not at the top level of control flow.
atexit is very capable and readable out of the box, for example:
import atexit
def goodbye():
print "You are now leaving the Python sector."
atexit.register(goodbye)
You can also use it as a decorator (as of 2.6; this example is from the docs):
import atexit
#atexit.register
def goodbye():
print "You are now leaving the Python sector."
If you wanted to make it specific to KeyboardInterrupt only, another person's answer to this question is probably better.
But note that the atexit module is only ~70 lines of code and it would not be hard to create a similar version that treats exceptions differently, for example passing the exceptions as arguments to the callback functions. (The limitation of atexit that would warrant a modified version: currently I can't conceive of a way for the exit-callback-functions to know about the exceptions; the atexit handler catches the exception, calls your callback(s), then re-raises that exception. But you could do this differently.)
For more info see:
Official documentation on atexit
The Python Module of the Week post, a good intro
You can prevent printing a stack trace for KeyboardInterrupt, without try: ... except KeyboardInterrupt: pass (the most obvious and propably "best" solution, but you already know it and asked for something else) by replacing sys.excepthook. Something like
def custom_excepthook(type, value, traceback):
if type is KeyboardInterrupt:
return # do nothing
else:
sys.__excepthook__(type, value, traceback)
I tried the suggested solutions by everyone, but I had to improvise code myself to actually make it work. Following is my improvised code:
import signal
import sys
import time
def signal_handler(signal, frame):
print('You pressed Ctrl+C!')
print(signal) # Value is 2 for CTRL + C
print(frame) # Where your execution of program is at moment - the Line Number
sys.exit(0)
#Assign Handler Function
signal.signal(signal.SIGINT, signal_handler)
# Simple Time Loop of 5 Seconds
secondsCount = 5
print('Press Ctrl+C in next '+str(secondsCount))
timeLoopRun = True
while timeLoopRun:
time.sleep(1)
if secondsCount < 1:
timeLoopRun = False
print('Closing in '+ str(secondsCount)+ ' seconds')
secondsCount = secondsCount - 1
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