Python在子執行緒無線迴圈的過程中,如果直接ctrl+c結束程式的話,雖然程式可以結束,但是會導致子執行緒資源無法回收,一般情況不會有太大影響,但是使用TCP通訊的時候,子執行緒是佔用特定的埠的,在資源沒有回收的情況下,再次啟動程式就會報端口占用錯誤可以手動回收資源如下:
# 我的套接字的埠是8899
$ netstat -nap | grep
# 會顯示程序號port
$ kill - port
所以參考https://blog.csdn.net/hp_cpp/article/details/83040162博主的方法如下強制結束子執行緒:
import inspect
import ctypes
from threading import Thread 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 Receive():
while 1:
print(1)
time.sleep(0.1) def Send():
while 1:
print(2)
time.sleep(0.1) if __name__ == "__main__":
t1 = Thread(target=Receive)
t2 = Thread(target=Send)
t1.start()
t2.start()
stop_thread(t1)
stop_thread(t2)
以下是我的測試程式,結合signal方法,主執行緒一直迴圈,一旦檢測到按下Ctrl+c,就會打印出'You pressed Ctrl+C!'這句話,並且呼叫上述方法結束兩個無限迴圈的子執行緒,最後呼叫exit()方法優雅的結束整個程式
import inspect
import ctypes
import signal
import sys
import time
from threading import Thread 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 signal_handler(signal, frame):
print('You pressed Ctrl+C!')
stop_thread(t1)
stop_thread(t2)
sys.exit() def Receive():
while 1:
print(1)
time.sleep(0.1) def Send():
while 1:
print(2)
time.sleep(0.1) if __name__ == "__main__":
t1 = Thread(target=Receive)
t2 = Thread(target=Send)
t1.start()
t2.start()
print(3)
while True:
signal.signal(signal.SIGINT, signal_handler)
print(4)
time.sleep(0.1)