Python多线程脚本未正常启动/工作
我快速写了这个示例脚本给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)
。我该如何让这个脚本正确运行,并在需要时退出呢?
2 个回答
你遇到了两个问题。第一个是你的程序结束得太早。第二个是你试图在 KeyEvent 线程中退出程序。
你的程序之所以早早结束,是因为你没有让主线程保持运行。你的主线程在执行完最后一行代码 kev.start() 后就结束了,而你的守护线程也随之停止了。
你需要一种方法让主线程一直保持运行(因为你希望用户输入 "y" 来退出程序)。有几种方法可以做到这一点。一个方法是在代码的最后加上
mainthread.join()
第二,sys.exit(0) 在你的 KeyEvent 线程中显然无法终止整个程序。你可以在下面的帖子中找到答案:为什么在 Python 中在线程内调用 sys.exit() 不会退出?
被标记为 daemon
的线程会在其他所有非守护线程结束时自动停止。在你的情况中,主线程在调用了两个守护线程的 start()
之后就结束了,这也导致了整个 Python 进程的结束。你的线程能否执行任何操作,完全是运气和时机的问题。
sys.exit(0)
只会结束主线程,而不会结束其他线程。你需要一种方法来通知你的线程该停止了。实现这一点的一种方法是使用 事件 对象。
不要使用 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