最早应该是stackoverflow上面的,在b站看到up主匿名者已逝的代码,觉得有意思,故复制下来研究研究。
import threading
import ctypes
import warnings
import time
class thread_with_exception(threading.Thread):
def __init__(self,task_function,callback_function=None):
threading.Thread.__init__(self)
self.task_function=task_function
self.callback_function=callback_function
self.stop=False
def run(self):
if not callable(self.task_function):
raise ValueError("callback_function parameter must be a function!")
# target function or thread class
try:
self.task_function()
finally:
if self.stop:
"""
这里应当做资源释放,减少强制杀死线程的影响
"""
print("线程被强制结束")
self.callback_function()
pass
def get_id(self):
# 各自线程返回的id
# returns id of the respective thread
if hasattr(self,'_thread_id'): # attribute 属性
return self._thread_id
for id,thread in threading._active.items():
if thread is self:
return id
def raise_exception(self):
#只有存活的线程才有必要强制结束
if not self.is_alive():
warnings.warn("no need to stop dead thread!")
return
thread_id=self.get_id()
res = ctypes.pythonapi.PyThreadState_SetAsyncExc(thread_id,ctypes.py_object(SystemExit))
if res==0:
warnings.warn("Invalid thread id!")
elif res>1:
ctypes.pythonapi.PyThreadState_SetAsyncExc(thread_id,0)
warnings.warn("Exception raise failure")
return
self.stop=True
if __name__ == "__main__":
from threading import Condition, Lock, RLock
from threading import Event
import _thread
self_condition=Condition()
nlock=_thread.allocate_lock()
# self_condition=RLock()
# clock = Lock()
# eflag = Event()
def user_task_func():
while True:
print("准备执行...")
self_condition.acquire()
self_condition.wait() # 想办法跳过wait阻塞函数
print("开始执行任务")
time.sleep(10.5)
nlock.acquire()
print("逻辑2执行完毕")
nlock.release()
print("执行用户任务结束")
self_condition.notify()
self_condition.release()
def release():
try:
self_condition.release()
nlock.release()
except Exception:
pass
print("结束子线程")
t1=thread_with_exception(user_task_func,release)
# t1.setDaemon(False) 默认是false,
# 如果某个子线程的daemon属性为False,主线程结束时会检测该子线程是否结束,如果该子线程还在运行,则主线程会等待它完成后再退出;
t1.start()
time.sleep(0.5)
# 注意以下三行,有无懂哥解释一下
self_condition.acquire()
self_condition.notify()
self_condition.release()
while True:
command=input()
if command=="kill":
t1.raise_exception()
if command=="exit":
break
print("检测子进程存活状态",t1.is_alive())
# print("检测子进程持有锁状态",self_condition)
print("主线程结束")
下面这个是51我心依旧大佬的博客。
import threading
import time
import inspect
import ctypes
def _async_raise(tid, exctype):
"""raises the exception, performs cleanup if needed"""
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):
_async_raise(thread.ident, SystemExit)
def print_time(e):
while 2:
print(e)
if __name__ == "__main__":
t = threading.Thread(target=print_time,args=("2"))
t.start()
time.sleep(0.001)
stop_thread(t)
print("stoped")
time.sleep(2)
t1 = threading.Thread(target=print_time,args=("1"))
t1.start()
time.sleep(0.001)
stop_thread(t1)
print("stoped")
while 1:
pass
参考链接