防止print()语句覆盖input()语句

时间:2018-02-11 17:51:00

标签: python python-3.x sockets

所以我正在使用python中的一个简单的聊天服务器。 服务器运行正常,在客户端上我有一个用于接收传入数据的线程和一个用于发送消息的线程。

我可以从client_1向服务器发送一条消息,然后将消息传递给所有其他客户端,然后打印该消息。

即使技术上一切正常,但只要发生这种情况,仍有一件事非常烦人:

假设client_1正在控制台中输入文本。 同时client_2向服务器发送消息,服务器将其发送到client_1,client_1打印消息。 现在,文本client_1最初在控制台中输入的内容已经不在它应该出现的行中了。

这是在client_2发送字符串“test test”之前控制台的样子:https://ibb.co/hFdeo7

这是他们发送后的样子:https://ibb.co/mEWAvn

注意:如果我在client_1上按Enter键,仍会正确发送“TEST TEST TEST”消息。问题只在于正在打印的文本与input()语句中的文本之间的冲突。

我的代码看起来像这样:

Server.py

connections = []

while True:
readable, writeable, exception = select.select(connections, [], [], 0)

for sock in readable:
    if sock == server:
        conn, addr = server.accept()
        connections.append(conn)

    else:
        data = str(sock.recv(1024), 'utf8')

        if data:
            for s in connections:
                if s != server_socket and s != sock:
                    s.send(bytes(data, 'utf8'))

        else:
            connections.remove(sock)

Client.py

def receive():
    while True:
        readable, writeable, exception = select.select([0, client], [], [])

        for sock in readable:
            if sock == client:
                data = str(sock.recv(1024), 'utf8')

                if data:
                    print(data)

def send():
    while True:
        readable, writeable, exception = select.select([0, client], [], [])

        for sock in readable:
            if sock == client:
                pass

            else:
                msg = input()
                client.send(bytes(msg, 'utf8'))

Thread(target=receive).start()
Thread(target=send).start()

如果没有在单独的脚本中运行send()和receive()函数,或者使用像Tkinter这样的GUI模块,有没有办法解决这个问题?

编辑:我想在收到消息后立即打印,但随后会显示输入()提示并再次输入文本。

1 个答案:

答案 0 :(得分:0)

这是显示传入消息然后重新显示输入提示和部分输入字符串(在注释中指定)的一种方法。它使用readline.get_line_buffer来读取当前输入的字符串并重新显示它。但是有一个警告:在没有锁定的情况下从不同的线程读取和写入相同的流将容易出现故障。

只需对receive函数进行少量修改:

if data:
    print('\n' + data)
    sys.stdout.write(readline.get_line_buffer())
    sys.stdout.flush()

'\n'中的print是因为传入的消息不会在所输入的内容之上。 flush是必需的,这样您就可以在没有换行符的情况下编写当前输入但不进行缓冲。我可能会建议向'> 'input添加提示(例如sys.stdout.write),以便让用户更清楚地了解正在发生的事情。

最后,运行此操作可能会弄乱您的终端输出。您可能需要在之后运行reset。可能有一种方法可以清理,但是我不知道它是什么。