Python:如何终止阻塞线程

时间:2011-02-16 16:52:32

标签: python multithreading

  

可能重复:
  Is there any way to kill a Thread in 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 :(得分:4)

这是一个更好的方法,在事件上使用“wait”命令,假设你想使用sleep。

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"

显然你需要将阻塞线程包装在使用上述模式的东西中,但是如果你不能另一个选择是让你的进程抛出异常,在我们的例子中我们基本上会杀死底层连接,这会导致异常,如果设置了停止标志,则发生异常时,我们会忽略它。

答案 1 :(得分:0)

你是对的,从docs,ident变量没有映射到线程id,它只是一个参考 -

  

<强> thread.get_ident()

     

返回当前线程的'线程标识符'。这是一个非零整数。它的价值没有直接意义;它旨在作为一种神奇的饼干用于例如索引特定于线程的数据的字典。当线程退出并创建另一个线程时,线程标识符可以被回收。

请参阅http://bytes.com/topic/python/answers/45247-terminating-thread-parent re:killling,不确定它是否正是您正在寻找的。