python问题,threading如何stop

self.th = threading.Thread(target=self.fun)
用 th.stop() 会报错 'Thread' object has no attribute 'stop',请教threading如何在运行过程中停止


from threading import Thread
import time
import inspect
import ctypes


def _async_raise(tid, exctype):
    tid = ctypes.c_long(tid)
    if not inspect.isclass(exctype):
        exctype = type(exctype)
    res = ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, ctypes.py_object(exctype))
    if res == 0:
        raise ValueError("invalid thread id")
    elif res != 1:
        # """if it returns a number greater than one, you're in trouble,
        # and you should call it again with exc=NULL to revert the effect"""
        ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, None)
        raise SystemError("PyThreadState_SetAsyncExc failed")


def stop_thread(thread):
    thread._is_stopped = True  # 修改线程状态
    _async_raise(thread.ident, SystemExit)


def task():
    for i in range(1, 100):
        print(i)
        time.sleep(1)


if __name__ == '__main__':
    th = Thread(target=task)
    th.start()  # 开始线程
    print(th.is_alive())  # 查看线程运行状态
    time.sleep(2)
    stop_thread(th)  # 终止线程
    print(th.is_alive())  # 查看线程运行状态

运行结果:

img

完全可以实现如下示例代码所示的Thread.stop方法:

import threading
import sys

class StopThread(StopIteration): pass

threading.SystemExit = SystemExit, StopThread

class Thread2(threading.Thread):

    def stop(self):
        self.__stop = True

    def _bootstrap(self):
        if threading._trace_hook is not None:
            raise ValueError('Cannot run thread with tracing!')
        self.__stop = False
        sys.settrace(self.__trace)
        super()._bootstrap()

    def __trace(self, frame, event, arg):
        if self.__stop:
            raise StopThread()
        return self.__trace


class Thread3(threading.Thread):

    def _bootstrap(self, stop_thread=False):
        def stop():
            nonlocal stop_thread
            stop_thread = True
        self.stop = stop

        def tracer(*_):
            if stop_thread:
                raise StopThread()
            return tracer
        sys.settrace(tracer)
        super()._bootstrap()

################################################################################

import time

def main():
    test = Thread2(target=printer)
    test.start()
    time.sleep(1)
    test.stop()
    test.join()

def printer():
    while True:
        print(time.time() % 1)
        time.sleep(0.1)

if __name__ == '__main__':
    main()

开启线程没有 stop 这个功能, .join() 是等待线程结束,可以在self.fun中 使用os.getpid() 获取到该线程的 pid号, 然后直接杀掉该线程即可