我很快为stackoverflow编写了这个示例脚本,所以忽略它的功能方面(我的版本看起来比这更好),但是:
from threading import Thread
from msvcrt import getch #I'm using Windows by the way.
from time import sleep
import sys
def KeyEvent():
while True:
key = getch()
if key.encode('hex') == '03': #^C
y = raw_input("Are you sure you want to quit? (y/n): ").lower()
if y == 'y':
sys.exit(0)
else: pass
def main():
t = 0
while True:
print "The count is {0}".format(t)
t +=1
sleep(1)
if __name__ == "__main__":
mainthread = Thread(target = main)
kev = Thread(target = KeyEvent)
mainthread.daemon = True
kev.daemon = True
mainthread.start()
kev.start()
这个脚本应该做的是同时运行两个循环,一个以秒为单位计数,而另一个检查^ C.请不要建议我使用其他方法,因为这是一个例子。
我的问题是,脚本无法启动。它显示“计数为0”并退出,但如果我完全省略.daemon = True
部分,则脚本会运行,但它不能正确运行sys.exit(0)
。如何使此脚本正确运行并在出现提示时退出?
答案 0 :(得分:2)
标记为daemon
的线程在每个其他非守护程序线程死亡时自动死亡。在你的情况下,主线程在你的两个守护进程线程上调用start()
后就死了,带来了python进程。在你的线程中完成任何事情都是运气和时间问题。
sys.exit(0)
不会杀死主线程以外的线程。你需要一种方法来告知你的线程是时候停止了。一种方法是通过Event对象。
你不应该使用getch
来尝试捕捉Ctrl + C,而是尝试使用信号处理程序:
from threading import Thread
from threading import Event
from time import sleep
import signal
stop = Event()
def handler(signum, frame):
y = raw_input("Are you sure you want to quit? (y/n): ").lower()
if y == 'y':
stop.set()
def main():
t = 0
while not stop.isSet():
print "The count is {0}".format(t)
t +=1
sleep(1)
if __name__ == "__main__":
signal.signal(signal.SIGINT, handler)
mainthread = Thread(target = main)
mainthread.start()
while mainthread.is_alive():
try:
mainthread.join(timeout = 0.1)
except IOError:
pass #Gets thrown when we interrupt the join
答案 1 :(得分:0)
你有两个问题。首先,你的课程结束得太早。其次是你试图退出KeyEvent线程中的程序。
您的程序提前终止,因为您没有保留主线程。您的主线程在您的最后一个语句kev.start()之后立即结束,并且您的守护程序线程随之死亡。
您需要一种机制来无限地保存主线程(因为您希望用户键入“y”以退出。)有几种方法可以执行此操作。一个是添加
mainthread.join()
到代码的末尾。
其次,KeyEvent线程中的sys.exit(0)显然无法终止整个程序。请在以下帖子中找到您的答案:Why does sys.exit() not exit when called inside a thread in Python?