💎一站式轻松地调用各大LLM模型接口,支持GPT4、智谱、星火、月之暗面及文生图 广告
### 主线程与子线程的结束顺序 主线程会等待所有的子线程执行结束再结束,除非设置子线程守护主线程。 ``` import threading import time def work(): for i in range(10): print("子线程工作中") time.sleep(0.2) if __name__ == '__main__': sub_thread = threading.Thread(target=work) sub_thread.start() time.sleep(1) print("主线程结束了") ``` 演示效果: ``` 子线程工作中 子线程工作中 子线程工作中 子线程工作中 子线程工作中 子线程工作中 子线程工作中 子线程工作中 子线程工作中 子线程工作中 主线程结束了 ``` > 注意,`target=work`与`target=work()`的执行结果是不一致的。使用target=work()时,主线程会等待子线程执行完毕。 ### 设置子线程守护主线程 #### 方法一 ``` sub_thread = threading.Thread(target=work, daemon=True) sub_thread.start() ``` #### 方法二 ``` sub_thread = threading.Thread(target=work) sub_thread.setDaemon(True) sub_thread.start() ``` 演示效果: ``` E:\PythonDevelop\zihan-python\06-basic>py 主线程和子线程的结束顺序.py 子线程工作中 子线程工作中 子线程工作中 子线程工作中 子线程工作中 主线程结束了 ``` ### 主动停止子线程 由于经常被Python非Daemon线程阻塞,导致程序无法结束。解决方案利用的是python内置API,通过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 test(): while True: print('-------') time.sleep(0.5) if __name__ == "__main__": t = threading.Thread(target=test) t.start() time.sleep(5.2) print("main thread sleep finish") stop_thread(t) ```