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

Python Socket多线程聊天客户端输入被干扰问题求助

解决多线程聊天客户端输入被打断的问题

核心原因

input()是阻塞式函数,用户输入过程中,接收线程的print()会直接输出到当前终端行,打乱正在输入的内容。

解决方案1:线程锁同步输入输出

给终端操作加全局锁,确保同一时间只有一个线程读写终端,避免冲突:

首先定义全局锁:

import threading
print_lock = threading.Lock()

修改接收消息的函数:

def recieve():
    while True:
        try:
            message = client.recv(1024).decode('ascii')
            with print_lock:
                # 回到行首清空当前输入内容,打印消息后重新显示输入提示
                print('\r', end='')
                print(message)
                print("Me: ", end='', flush=True)
        except:
            print("连接断开")
            client.close()
            break

修改发送消息的函数:

def write():
    while True:
        with print_lock:
            message = input("Me: ")
        message = formatMess(nickname, message)
        client.send(message.encode('ascii'))

解决方案2:非阻塞输入监听(需额外库)

用pynput监听键盘输入,实时控制输入状态,收到消息时自动调整显示:

先安装依赖:

pip install pynput

示例代码:

from pynput.keyboard import Listener, Key
import threading

current_input = ""
print_lock = threading.Lock()

def on_press(key):
    global current_input
    try:
        current_input += key.char
        with print_lock:
            print(f"\rMe: {current_input}", end='', flush=True)
    except AttributeError:
        if key == Key.backspace:
            current_input = current_input[:-1]
            with print_lock:
                print(f"\rMe: {current_input}", end='', flush=True)
        elif key == Key.enter:
            with print_lock:
                print()
            message = formatMess(nickname, current_input)
            client.send(message.encode('ascii'))
            current_input = ""
            with print_lock:
                print("Me: ", end='', flush=True)

def recieve():
    while True:
        try:
            message = client.recv(1024).decode('ascii')
            with print_lock:
                print(f"\r{message}\nMe: {current_input}", end='', flush=True)
        except:
            print("连接断开")
            client.close()
            break

# 启动线程
recieve_thread = threading.Thread(target=recieve)
recieve_thread.start()

# 启动键盘监听
with Listener(on_press=on_press) as listener:
    listener.join()

注意事项

  • 线程锁方案更轻量,适合基础场景;非阻塞输入更灵活,但需要额外依赖。
  • 所有终端输出操作必须通过锁保护,避免并发冲突。

内容的提问来源于stack exchange,提问作者Beni

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 11:55:46