I'm trying to create a method which r开发者_如何转开发uns on a timer in the background of my main script:
def hello_world(self):
print 'Hello!'
threading.Timer(2,hello_world).start()
if __name__ == "__main__":
try:
hello_world()
except KeyboardInterrupt:
print '\nGoodbye!'
I am getting this message when I attempt to keyboard interrupt my script:
Exception KeyboardInterrupt in <module 'threading' from '/System/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/threading.py'> ignored
How do I close the thread so that I can exit my application cleanly?
To elaborate a bit on Aphex's answer, the main thread can't possibly catch the KeyboardInterrupt signal, unless you have very fast fingers. The main thread exits almost immediately! Try this:
import threading
def hello_world():
print 'Hello!'
threading.Timer(2,hello_world).start()
if __name__ == "__main__":
try:
hello_world()
except KeyboardInterrupt:
print '\nGoodbye!'
print "main thread exited"
More generally, I would not suggest using a self-calling timer like this, just because it creates a lot of threads. Just create one thread and call time.sleep
inside it.
However, as long as you keep the main thread running, you seem to be able to catch KeyboardInterrupt
inside. The trick then is to make the thread a daemon
thread that exits when the main thread exits.
import threading
import time
def hello_world():
while(True):
print 'Hello!'
time.sleep(2)
if __name__ == "__main__":
hw_thread = threading.Thread(target = hello_world)
hw_thread.daemon = True
hw_thread.start()
try:
time.sleep(1000)
except KeyboardInterrupt:
print '\nGoodbye!'
This exits automatically after 1000 seconds -- you could make that number even bigger if you like. You could also use a busy-loop to repeat the sleep call, but I don't really see the point.
You just need to set the Timer
thread as a daemon
def hello_world(self):
print 'Hello!'
t = threading.Timer(2,hello_world)
t.daemon = True
t.start()
That will cause it to exit when the main thread exits, e.g. due to KeyboardInterrupt
.
The daemon
setting causes the entire program to exit when the only threads left are daemon
threads.
Try re-raising the KeyboardInterrupt
exception: http://effbot.org/zone/stupid-exceptions-keyboardinterrupt.htm
This still may not work though; chances are you're running into this caveat:
Threads interact strangely with interrupts: the KeyboardInterrupt exception will be received by an arbitrary thread. (When the signal module is available, interrupts always go to the main thread.)
In short, you can't be sure that the KeyboardInterrupt
is going to your main thread. To workaround this, you may want to look into the signal
module.
Edit: A more elegant way to cancel the thread is to have a shared variable that the thread looks at, and exits if it becomes false
. Then if you want to kill the thread from your main thread, you set the variable to false
.
精彩评论