简体   繁体   中英

Python: readline/input() interacting with output from different threads

I'm writing a multithreaded program with an interactive console:

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

However, a library I'm using runs my callbacks from a different thread. The callback needs to print to the console. Thus I want to clear the command line, re-display the prompt, and re-show the command line.

How do I do that, short of re-implementing readline ?

Starting from this answer that solves the issue for C, I arrived at the following Python code, which works well enough for my purposes:

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

  • uses \\r\\x1b[K ( CR + CSI code EL ) to remove the existing Readline prompt
  • prints its payload line
  • sends SIGWINCH to the thread that runs readline (in my case, readline runs in the main thread so os.getpid() gives the right target PID); this causes readline to re-draw its full prompt.

Possible remaining issues:

  • As mentioned in the other answer, if the readline prompt is longer than one line, the line-clearing will most likely fail.
  • You need to acquire the print_lock whenever printing in the main thread (this is true independent of the readline issue)
  • There might be some racy behaviours when the user presses a key at the exact same moment when the background thread prints.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM