Python:如何在不覆盖当前输入的情况下打印输出?

3

如何在不覆盖已输入但未发送的内容的情况下打印内容?

这是一个套接字的客户端,我想要从服务器打印消息,而不会覆盖/追加当前已输入的内容。

def listen():
    while True:
        data = s.recv(1024)
        print(data.decode('utf-8'))

def write():
    while True:
        text = input("Text > ")
        s.sendall(bytes(text, 'utf-8'))

listener = threading.Thread(target=listen)
listener.start()

writer = threading.Thread(target=write)
writer.start()

我想将接收到的数据打印在当前输入行的上方或下方,但现在它只是将其写在输入行上。
2个回答

1

交互式终端输入很复杂,通常需要使用库来处理,直接处理它很困难。对于行输入,readline 及其替代品如 libedit 很受欢迎。大多数 shell 和 REPL 都使用这些库。

Python 标准库有 readline 模块,它是与 readlinelibedit 的接口。导入它使得 input 使用 realine/libedit,因此可以获得光标导航、自动完成和历史记录功能。并且它允许在终端中画完东西后重新绘制输入行。

要在上一行打印内容,可以使用 ANSI 转义序列。

import threading
import sys
from time import sleep
import readline # importing readline makes input() use it

def listen():
    i = 0
    while True:
        i += 1
        sleep(1)
        # <esc>[s - save cursor position
        # <esc>[1A - move cursor up
        # \r - carriage return
        # print message
        # <esc>[u - restore cursor position
        sys.stdout.write("\x1b[s\x1b[1A\rOutput: "+str(i)+"\x1b[u")
        readline.redisplay()

def write():
    while True:
        print "" # make space for printing messages
        text = input("Text > ")

listener = threading.Thread(target=listen)
listener.daemon = True
listener.start()

write()

readline 库还具有 rl_message 和其他有用的功能,但它不被 Python 的 readline 模块导出。


(我不确定我的方法是否是正确的,以及它在终端和readline版本之间是否百分之百可移植。) - kolen

0
s.sendall(bytes(text, 'utf-8'))之后添加time.sleep(10),因为您立即进行输入,而数据稍后接收和打印。使用time.sleep可以给数据接收和打印留出时间。
但是,如果您输入input的数据太慢,这并不能帮助您。通常情况下,代码很奇怪,因为为什么要在同一个终端上执行inputprint?在现实生活中这没有意义。
对于学术目的,您可以尝试这个:
is_input_active = False

def listen():
    while True:
        data = s.recv(1024)
        while is_input_active:
            time.sleep(0.2)
        print(data.decode('utf-8'))

def write():
    global is_input_active
    while True:
        is_input_active = True
        text = input("Text > ")
        is_input_active = False
        s.sendall(bytes(text, 'utf-8'))

在这个版本中,listen() 将阻塞直到 input 函数完成。如果不想要这样,可以尝试像这样做:

def listen():
    data = b''
    while True:
        data += s.recv(1024)  # accumulate
        while not is_input_active:
            print(data.decode('utf-8'))
            data = b''  # reset

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接