【问题标题】:Python: readline/input() interacting with output from different threadsPython:readline/input() 与来自不同线程的输出交互
【发布时间】:2018-09-24 07:52:53
【问题描述】:

我正在编写一个带有交互式控制台的多线程程序:

def console()
    import readline
    while True:
        data = input()
        do_whatever(data.split())

但是,我正在使用的库从不同的线程运行我的回调。回调需要打印到控制台。因此我想清除命令行,重新显示提示,重新显示命令行。

如果不重新实现readline,我该怎么做?

【问题讨论】:

  • 您需要回调打印到 stdout/stderr 吗?一种快速而丑陋的技巧是打印许多“新行”来刷新整个屏幕。或根据操作系统执行“clear”或“cls”等系统命令。
  • 我无法进行全屏刷新,因为我需要回滚缓冲区。此外,这并没有告诉我如何重写 readline 提示以及用户正在输入的任何内容。
  • 您找到解决问题的方法了吗?一个开箱即用的解决方案可能是在您的程序周围使用rlwrap,而不是使用 Python 中的 readline。

标签: python multithreading readline


【解决方案1】:

从解决 C 问题的this answer 开始,我得到了以下 Python 代码,该代码足以满足我的目的:

import os
import readline
import signal
import sys
import time
import threading


print_lock = threading.Lock()

def print_safely(text):
    with print_lock:
        sys.stdout.write(f'\r\x1b[K{text}\n')
        os.kill(os.getpid(), signal.SIGWINCH)

def background_thread():
    while True:
        time.sleep(0.5)
        print_safely('x')

threading.Thread(target=background_thread, daemon=True).start()

while True:
    try:
        inp = input(f'> ')
        with print_lock:
            print(repr(inp))
    except (KeyboardInterrupt, EOFError):
        print('')
        break

print_safely

  • 使用\r\x1b[K (CR + CSI code EL) 删除现有的 Readline 提示
  • 打印其有效载荷行
  • 发送 SIGWINCH 到运行 readline 的线程(在我的例子中,readline 在主线程中运行,所以 os.getpid() 给出了正确的目标 PID);这会导致 readline 重新绘制其完整提示。

可能的剩余问题:

  • 正如另一个答案中提到的,如果 readline 提示长于一行,则行清除很可能会失败。
  • 您需要在主线程中打印时获取 print_lock(这与 readline 问题无关)
  • 当用户在后台线程打印的同时按下某个键时,可能会出现一些不雅行为。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-09
    相关资源
    最近更新 更多