I want to write a python program (run.py) that always runs and only stops running when Ctr-C is pressed. This is how I implement it:
wrapper.py:
import subprocess
import signal
def sig_handler(signum, frame):
res = input("Ctrl-c was pressed. Do you really want to exit? y/n ")
if res == 'y':
exit(1)
signal.signal(signal.SIGINT, sig_handler)
while(True):
p = None
p = subprocess.Popen("python run.py", shell=True)
stdout, stderr = p.communicate()
run.py:
print('aaaaa')
print('bbbbb')
However, when I hold left-mouse and select text in the terminal that is running wrapper.py, this event is understood incorrectly as Ctr-C then the wrapper.py stop running run.py. My question is how to prevent reading mouse events as KeyboardInterrupt in python (Unix). Thanks!
Terminal
Instead of using a module like signal to achieve this you could opt to use exceptions since it is a pretty exceptional case that your program will receive a keyboard interrupt.
#!/usr/bin/env python3
import sys
def main() -> int:
try:
while True:
print(sys.argv)
except KeyboardInterrupt as e:
return 0
if __name__ == '__main__':
try:
sys.exit(main())
except Exception as e:
print(f'Error: {e}', file=sys.stderr)
sys.exit(1)
The source code has no problem. The problem is caused by dictionary software. The software has a feature of selecting word to translate. By somehow it converts the mouse event (selecting word) to Ctr-C then the program above exits. When I turn off the dictionary software, the problem disappears. I will close the thread here
Related
Was given a script I would reuse more or less, I need to be able to to both :
end the execution by itself
capture ctrl-c to exit on user action
I saw many clues to the second part on other answers/question of stackoverflow similar to :
try:
while True:
time.sleep(1)
except (KeyboardInterrupt, SystemExit):
pass
In my point of view I should run the execution functions (main) in
while mycondition:
try:
mainfunction()
except KeyboardInterrupt:
personalised_exit()
Why not (if I undersoud well as I am still a python noob), but why not a more declarative code with usage of signal modules ?
something might look then like
import signal
import sys
def signal_handler(sig, frame):
[...]
sys.exit(0)
signal.signal(signal.SIGINT, signal_handler)
main()
signal.pause()
I run the following code in a cmd window. Many different exceptions may occur within the try loop, this is why I generalize to except all exceptions. But: If I close the cmd window the code runs in, how do I stop the code from keep running even though the cmd window is closed.
while True:
try:
print('test') # in actual code more complicateed task with many possible exceptions
except Exception:
pass
Right now, I can only quit this code via a restart.
EDIT: I tried to catch the exception but the log file only says "log works"
import sys
from time import sleep
import logging
logging.basicConfig(filename="logtest.log",
filemode='a',
format='%(asctime)s,%(msecs)d %(name)s %
(levelname)s %(message)s',
datefmt='%H:%M:%S',
level=logging.DEBUG)
logging.info("log works")
while True:
try:
print('test')
sleep(1)
except Exception as e:
logging.info(e)
logging.info(str(e))
This is because in your try statement you need to set a condition where the execution breaks for example below:
x = 0
while True:
try:
if (x == 10):
break
else:
# in actual code more complicated task with many possible exceptions
print('test')
x += 1
except Exception as e:
print(e.printStackTrace())
Another method can be using a keyword to force break out of the while loop for example below we are using q to end the loop execution:
'''
from time import sleep
import re
input_text= ""
while True:
try:
# in actual code more complicateed task with many possible exceptions
input_text = input("Enter your selection .....")
print(input_text)
if re.search('q' , input_text , re.IGNORECASE):
break
except Exception as e:
print(e.printStackTrace())
'''
Well, your script never received any exception, it was just killed without any possibility to log anything.
We are not in the Unix world where a shell just kindly telss its child that it is exiting with a SIGHUP signal letting them know where they want to die or not. We are in a MS/DOS inheritance: when a console ends, every process attached to the console dies.
So unless you have detached the process from its console it is over. You can easily control it with Windows task manager (start it with Ctrl Alt Del)
I wrote those test python code as following:
import signal
import time
import os
def handler(signum, frame):
print "do whatever, like call thread.interrupt_main()"
return
signal.signal(signal.SIGINT, handler)
while 1:
try:
time.sleep(10)
except:
os.kill(int(os.getpid()), signal.SIGINT)
pass
when i excute this test code on windows, the process print "do whatever, like call thread.interrupt_main()", then exit;
on linux, it works correctly.
why on windows it not work?
http://docs.python.org/2/library/os.html#os.kill
Windows: The signal.CTRL_C_EVENT and signal.CTRL_BREAK_EVENT signals
are special signals which can only be sent to console processes which
share a common console window, e.g., some subprocesses. Any other
value for sig will cause the process to be unconditionally killed by
the TerminateProcess API, and the exit code will be set to sig.
Try following code:
import time
while 1:
try:
time.sleep(1)
except KeyboardInterrupt:
print "do whatever, like call thread.interrupt_main()"
I have my main application thread that spawns 2 threads and I catch SIGINT in my main thread to quit them nicely.
On linux, I'm using signal.pause() and it works perfectly.
What is the best way to implement signal.pause() on Windows?
My ugly solution is:
my_queue.get(True, averylongtime)
And put something in my_queue in my signal handler. Note that if I don't specify a timeout, SIGINT is not caught. But I wonder if there's a better solution.
Thank you
I use this:
#another:
while not self.quit:
# your code
# main
try:
# your code
except KeyboardInterrupt:
another.quit = True
time.sleep(5) # or wait for threading.enumerate() or similar
If I want it more robust, say, exit in presence of bugs too:
except KeyboardInterrupt:
another.quit = True
signal.alarm(5)
time.sleep(6)
A side effect to this is that every block where you except: or except Exception, e: (which is not something you should do anyway/much) you have to prepend except KeyboardInterrupt: raise so that the exception is not "eaten".
I use this for catching a ctrl-c on windows. In case I'm writing to a pipe or file or what have you.. I want to exit gracefully. Below is a toy example
import signal
import sys
def signal_handler(signal, frame):
print('Process Interrupted!\n\a')
sys.exit(0)
signal.signal(signal.SIGINT,signal_handler)
#Rest of your code
In python when running scripts is there a way to stop the console window from closing after spitting out the traceback?
You can register a top-level exception handler that keeps the application alive when an unhandled exception occurs:
def show_exception_and_exit(exc_type, exc_value, tb):
import traceback
traceback.print_exception(exc_type, exc_value, tb)
raw_input("Press key to exit.")
sys.exit(-1)
import sys
sys.excepthook = show_exception_and_exit
This is especially useful if you have exceptions occuring inside event handlers that are called from C code, which often do not propagate the errors.
If you doing this on a Windows OS, you can prefix the target of your shortcut with:
C:\WINDOWS\system32\cmd.exe /K <command>
This will prevent the window from closing when the command exits.
try:
#do some stuff
1/0 #stuff that generated the exception
except Exception as ex:
print ex
raw_input()
On UNIX systems (Windows has already been covered above...) you can change the interpreter argument to include the -i flag:
#!/usr/bin/python -i
From the man page:
-i
When a script is passed as first argument or the -c option is used, enter interactive mode after executing the script or the command. It does not read the $PYTHONSTARTUP file. This can be useful to inspect global variables or a stack trace when a script raises an exception.
You could have a second script, which imports/runs your main code. This script would catch all exceptions, and print a traceback (then wait for user input before ending)
Assuming your code is structured using the if __name__ == "__main__": main() idiom..
def myfunction():
pass
class Myclass():
pass
def main():
c = Myclass()
myfunction(c)
if __name__ == "__main__":
main()
..and the file is named "myscriptname.py" (obviously that can be changed), the following will work
from myscriptname import main as myscript_main
try:
myscript_main()
except Exception, errormsg:
print "Script errored!"
print "Error message: %s" % errormsg
print "Traceback:"
import traceback
traceback.print_exc()
print "Press return to exit.."
raw_input()
(Note that raw_input() has been replaced by input() in Python 3)
If you don't have a main() function, you would use put the import statement in the try: block:
try:
import myscriptname
except [...]
A better solution, one that requires no extra wrapper-scripts, is to run the script either from IDLE, or the command line..
On Windows, go to Start > Run, enter cmd and enter. Then enter something like..
cd "\Path\To Your\ Script\"
\Python\bin\python.exe myscriptname.py
(If you installed Python into C:\Python\)
On Linux/Mac OS X it's a bit easier, you just run cd /home/your/script/ then python myscriptname.py
The easiest way would be to use IDLE, launch IDLE, open the script and click the run button (F5 or Ctrl+F5 I think). When the script exits, the window will not close automatically, so you can see any errors
Also, as Chris Thornhill suggested, on Windows, you can create a shortcut to your script, and in it's Properties prefix the target with..
C:\WINDOWS\system32\cmd.exe /K [existing command]
From http://www.computerhope.com/cmd.htm:
/K command - Executes the specified command and continues running.
In windows instead of double clicking the py file you can drag it into an already open CMD window, and then hit enter. It stays open after an exception.
Dan
if you are using windows you could do this
import os
#code here
os.system('pause')
Take a look at answer of this question: How to find exit code or reason when atexit callback is called in Python?
You can just copy this ExitHooks class, then customize your own foo function then register it to atexit.
import atexit
import sys, os
class ExitHooks(object):
def __init__(self):
self.exit_code = None
self.exception = None
def hook(self):
self._orig_exit = sys.exit
sys.exit = self.exit
sys.excepthook = self.exc_handler
def exit(self, code=0):
self.exit_code = code
self._orig_exit(code)
def exc_handler(self, exc_type, exc, *args):
self.exception = exc
hooks = ExitHooks()
hooks.hook()
def goodbye():
if not (hooks.exit_code is None and hooks.exception is None):
os.system('pause')
# input("\nPress Enter key to exit.")
atexit.register(goodbye)
Your question is not very clear, but I assume that the python interpreter exits (and therefore the calling console window closes) when an exception happens.
You need to modify your python application to catch the exception and print it without exiting the interpreter. One way to do that is to print "press ENTER to exit" and then read some input from the console window, effectively waiting for the user to press Enter.