Python程序中如何退出自定义两个线程?输入break无法终止程序
问题分析
你的代码存在几个关键问题导致输入"break"无法终止程序:
- 主线程重复调用send()函数:main函数中启动send线程(y)后,又直接调用了
send(),这会让主线程也进入send的输入循环,和y线程是完全独立的执行流程,你输入的"break"只会终止其中一个send流程,而非整个程序。 - recv线程无终止条件:recv函数是无限
while True循环,没有任何退出判断,即使send线程结束,recv线程仍会持续阻塞在conn.recv()调用上,导致程序无法退出。 - 线程等待逻辑错误:主线程的
if not send()判断完全无效,因为send()函数没有返回值(默认返回None),且该调用和已启动的y线程无关,无法触发后续的线程join和资源关闭逻辑。
修正方案
我们可以通过全局停止标志+正确的线程等待逻辑来实现优雅终止,同时处理socket操作的异常:
import socket import threading IP = "127.0.0.1" PORT = 25565 # 全局停止标志,用于通知recv线程退出 stop_flag = False server_sock = None conn = None def recv(): global stop_flag, conn while not stop_flag: try: income_message = conn.recv(1024) if not income_message: # 客户端关闭连接,recv返回空字节串 print("客户端已断开连接") break print("client: " + income_message.decode()) except Exception as e: print(f"接收消息出错: {e}") break def send(): global stop_flag, conn while True: message = input("") try: conn.send(message.encode()) if message == "break": stop_flag = True break except Exception as e: print(f"发送消息出错: {e}") stop_flag = True break def main(): global server_sock, conn server_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) server_sock.bind((IP, PORT)) server_sock.listen() print("等待客户端连接...") conn, addr = server_sock.accept() print(f"客户端 {addr} 已连接") x = threading.Thread(target=recv, args=()) x.start() y = threading.Thread(target=send, args=()) y.start() print("线程已启动!") # 等待send线程结束 y.join() # 等待recv线程结束 x.join() # 关闭连接和socket conn.close() server_sock.close() print("程序已停止") if __name__ == "__main__": main()
关键改进点
- 全局停止标志:用
stop_flag通知recv线程退出循环,避免无意义的阻塞。 - 移除重复的send()调用:主线程不再执行send函数,只负责启动线程和等待线程结束。
- 异常处理:对socket的recv和send操作添加异常捕获,处理连接中断等异常情况。
- 正确的资源释放:在所有线程结束后,依次关闭客户端连接和服务器socket。
另外,如果你想更简洁的实现,可以将recv线程设置为守护线程(x.daemon = True),这样当主线程结束时,recv线程会自动被终止,但这种方式不够优雅,因为可能会导致recv线程的资源未正常释放,推荐使用上面的标志位方式。
内容的提问来源于stack exchange,提问作者Tal Roz
相关产品推荐
相关产品推荐

