You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 12:05:19