优雅的线程终止
通常不鼓励突然终止线程,尤其是在 Python 中。如果关键操作被中断,可能会导致资源泄漏或数据损坏。
推荐方法
首选方法是设置一个标志或信号量来指示线程应该退出。线程应定期检查此标志,如果已设置,则正常退出。
示例:
import threading class StoppableThread(threading.Thread): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self._stop_event = threading.Event() def stop(self): self._stop_event.set() def stopped(self): return self._stop_event.is_set()
在此示例中,调用 stop() 向线程发出信号退出,然后使用 join() 等待它优雅地完成。
强制终止
在特殊情况下,您可能需要强制终止线程。但是,这应该被视为最后的手段。
强制终止方法:
import ctypes import inspect def _async_raise(tid, exctype): 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)) if res == 0: raise ValueError("invalid thread id") elif res != 1: ctypes.pythonapi.PyThreadState_SetAsyncExc(ctypes.c_long(tid), None) raise SystemError("PyThreadState_SetAsyncExc failed") class ThreadWithExc(threading.Thread): def _get_my_tid(self): if not self.is_alive(): # Note: self.isAlive() on older version of Python raise threading.ThreadError("the thread is not active") # do we have it cached? if hasattr(self, "_thread_id"): return self._thread_id # no, look for it in the _active dict for tid, tobj in threading._active.items(): if tobj is self: self._thread_id = tid return tid raise AssertionError("could not determine the thread's id") def raise_exc(self, exctype): _async_raise(self._get_my_tid(), exctype )
此方法依赖于 PyThreadState_SetAsyncExc 函数在特定的环境中引发异常线。但是,需要注意的是,此方法并不完全可靠,如果线程处于 Python 解释器之外的系统调用中,则可能会失败。
注意事项:
以上是如何在Python中优雅地终止线程,什么时候需要强制终止?的详细内容。更多信息请关注PHP中文网其他相关文章!