【问题标题】:Prevent print() statement from overwriting text from input() statement防止 print() 语句覆盖 input() 语句中的文本
【发布时间】:2018-02-11 17:50:59
【问题描述】:

所以我正在使用 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() 语句中的文本之间的冲突。

我的代码如下所示:

服务器.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)

客户端.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 模块?

编辑:我想在收到传入消息后立即打印,然后显示 input() 提示并在之后再次键入文本。

【问题讨论】:

  • 我认为你没有说清楚的一件事是你想要在这种情况下发生什么。如果用户正在键入,客户端是否应该等待显示收到的消息?消息是否应该显示在不同的位置?是否应该打印传入的消息,然后再次显示输入提示和键入的文本?这些都是我见过的解决方案。
  • 对我来说最好的办法是打印传入的消息并在之后再次显示输入提示和键入的文本。

标签: python python-3.x sockets


【解决方案1】:

这是显示传入消息然后重新显示输入提示和部分输入字符串(如注释中指定)的一种方法。它使用readline.get_line_buffer 读取当前输入的字符串并重新显示它。不过警告:从不同线程读取和写入同一流而不加锁很容易出现故障。

只需要对receive 函数做一个小的修改:

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

print 中的 '\n' 是这样,传入的消息不会正好落在正在输入的内容之上。 flush 是必需的,这样您就可以在没有换行符的情况下写入当前输入,但不会缓冲它。我可能会建议在inputsys.stdout.write 中添加一个提示(如'> '),只是为了让用户更清楚正在发生的事情。

最后,运行它可能会弄乱您的终端输出。之后您可能需要运行reset。可能有一种清理方法可以防止这种情况发生,但我不知道它是什么。

【讨论】:

    猜你喜欢
    • 2016-12-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-08-03
    • 2021-03-01
    • 1970-01-01
    • 2010-09-21
    相关资源
    最近更新 更多