Python:如何终止一个阻塞线程
可能重复的问题:
在Python中有没有办法终止一个线程?
这个问题是对之前一个解决方案的后续提问。基本上,它讨论的是如何通过编程的方式终止一个线程:http://sebulba.wikispaces.com/recipe+thread2
不过这个方法并没有奏效……我想知道有没有人能解释一下,如何终止一个正在阻塞的线程?我猜测可能是因为我没有提供正确的线程ID,但我做了一些测试,觉得我应该可以直接使用iden。
如果真的是线程ID的问题,那我该如何获取正确的线程ID呢?
测试代码:
class BlockingTestThread(Thread):
def __init__(self):
self._running_flag = False
Thread.__init__(self, target=self.test_method)
def test_method(self):
try:
while(not self.stopped()):
self._running_flag = True
time.sleep(100)
finally:
self._running_flag = False
def _async_raise(tid, exctype):
'''Raises an exception in the threads with id tid'''
if not inspect.isclass(exctype):
raise TypeError("Only types can be raised (not instances)")
res = ctypes.pythonapi.PyThreadState_SetAsyncExc(ctypes.c_long(tid), ctypes.py_object(exctype))
time.sleep(0.1)
if __name__ == "__main__":
thread = BlockingTestThread()
thread.start()
_async_raise(thread.ident, SystemExit)
print "Joining thread"
thread.join()
print "Done Joining thread"
#will never get here!
2 个回答
0
你说得对,关于ident这个变量,从文档来看,它并不是线程的ID,而只是一个引用。
thread.get_ident()
这个函数会返回当前线程的“线程标识符”。它是一个非零的整数。这个值本身没有特别的意义;它主要是用来作为一个“魔法饼干”,比如用来在一个字典中查找与线程相关的数据。当一个线程结束后,可能会重新使用这个线程标识符给新创建的线程。
关于终止线程的内容,可以参考这个链接:http://bytes.com/topic/python/answers/45247-terminating-thread-parent,不过我不太确定这是否正是你想要的。
3
这里有个更好的方法,就是在事件上使用“wait”命令,假设你想用睡眠功能。
class BlockingTestThread(Thread):
def __init__(self):
self._running_flag = False
self.stop = threading.Event()
Thread.__init__(self, target=self.test_method)
def test_method(self):
try:
while(not self.stop.wait(1)):
self._running_flag = True
print 'Start wait'
self.stop.wait(100)
print 'Done waiting'
finally:
self._running_flag = False
def terminate(self):
self.stop.set()
if __name__ == "__main__":
thread = BlockingTestThread()
thread.start()
time.sleep(2)
print 'Time sleep 2'
thread.terminate()
print "Joining thread"
thread.join()
print "Done Joining thread"
显然,你需要把你的阻塞线程放在上面提到的模式中,但如果你做不到,另一种选择就是让你的程序抛出一个异常。在我们的例子中,我们基本上是关闭了底层连接,这样就会产生一个异常。当这个异常发生时,如果停止标志被设置,我们就会忽略它。