Print text before input() prompt in python

后端 未结 3 1036
别跟我提以往
别跟我提以往 2020-12-06 08:31

In Python, is it possible to request user input with input() in the console while simultaneously printing out text in the line BEFORE the prompt? It should look something li

3条回答
  •  春和景丽
    2020-12-06 09:16

    Here's another approach using ANSI/VT100 terminal control escape sequences.

    We tell the terminal to only scroll the upper region of the terminal, where the output data is printed, so that the lower region, where the input prompt is printed, stays fixed in place. When we exit the program (using Ctrl C) we need to restore the default scrolling settings.

    This program first clears the screen and then sits in a loop prompting the user for a number n and then prints the numbers in range(n), one per line, with a small time delay to make it easier to see what's happening. The output for each range follows on from the previous range. If the user enters a non-integer the prompt is re-printed. The readline module is imported so that editing and history are available at the input prompt; this module may not be available on all platforms.

    First, a Python 2 version.

    ''' Print text in a scrolling region of the terminal above a fixed line for input
    
        Written by PM 2Ring 2016.05.29
    
        Python 2 version
    '''
    
    from __future__ import print_function
    from time import sleep
    import readline
    
    # Some ANSI/VT100 Terminal Control Escape Sequences
    CSI = '\x1b['
    CLEAR = CSI + '2J'
    CLEAR_LINE = CSI + '2K'
    SAVE_CURSOR = CSI + 's'
    UNSAVE_CURSOR = CSI + 'u'
    
    def emit(*args):
        print(*args, sep='', end='')
    
    def set_scroll(n):
        return CSI + '0;%dr' % n
    
    # Height of scrolling region
    height = 40
    
    GOTO_INPUT = CSI + '%d;0H' % (height + 1)
    
    emit(CLEAR, set_scroll(height))
    
    try:
        while True:
            #Get input
            emit(SAVE_CURSOR, GOTO_INPUT, CLEAR_LINE)
            try:
                n = int(raw_input('Number: '))
            except ValueError:
                continue
            finally:
                emit(UNSAVE_CURSOR)
    
            #Display some output
            for i in range(n):
                print(i)
                sleep(0.1)
    
    except KeyboardInterrupt:
        #Disable scrolling, but leave cursor below the input row
        emit(set_scroll(0), GOTO_INPUT, '\n')
    

    And here's a version that runs on Python 2 and Python 3. When run on Python 3 this script calls shutil.get_terminal_size() to set the height of the scrolling region. It is possible to get the terminal size in Python 2, but the code is rather messy, so I opted for a fixed height.

    I should mention that both versions of this script don't cope well if the terminal size is changed while they are running; handling that properly is left as an exercise for the reader. :)

    ''' Print text in a scrolling region of the terminal above a fixed line for input
    
        Written by PM 2Ring 2016.05.29
    
        Python 2 / 3 version
    '''
    
    from __future__ import print_function
    import sys
    import readline
    from time import sleep
    
    if sys.version_info > (3,):
        # Get the (current) number of lines in the terminal
        import shutil
        height = shutil.get_terminal_size().lines - 1
    
        stdout_write_bytes = sys.stdout.buffer.write
    else:
        height = 40
        input = raw_input
        stdout_write_bytes = sys.stdout.write
    
    
    # Some ANSI/VT100 Terminal Control Escape Sequences
    CSI = b'\x1b['
    CLEAR = CSI + b'2J'
    CLEAR_LINE = CSI + b'2K'
    SAVE_CURSOR = CSI + b's'
    UNSAVE_CURSOR = CSI + b'u'
    
    GOTO_INPUT = CSI + b'%d;0H' % (height + 1)
    
    def emit(*args):
        stdout_write_bytes(b''.join(args))
    
    def set_scroll(n):
        return CSI + b'0;%dr' % n
    
    emit(CLEAR, set_scroll(height))
    
    try:
        while True:
            #Get input
            emit(SAVE_CURSOR, GOTO_INPUT, CLEAR_LINE)
            try:
                n = int(input('Number: '))
            except ValueError:
                continue
            finally:
                emit(UNSAVE_CURSOR)
    
            #Display some output
            for i in range(n):
                print(i)
                sleep(0.1)
    
    except KeyboardInterrupt:
        #Disable scrolling, but leave cursor below the input row
        emit(set_scroll(0), GOTO_INPUT, b'\n')
    

提交回复
热议问题