Move the Cursor Back For taking Input Python

Solution 1:

Having looked at this further, my final solution is to create my own custom input. NB: this only works in windows command prompt. If you are looking to do this in Unix you will have to look into an alternative. I may update this answer later to support Unix. [Edit: Updated to support both Unix and Windows]

Again, this will not work in IDLE

This function takes a prefix for your input, the number of max_length of the input, and the blank_char to fill the length of the input with.

First, we capture the user input and if it is a displayable character, we add it to our word. Every time we get a new character we overwrite the existing input line to keep up to date with the current state of the word.

We also look for the b'\x08' charater (backspace) so we can remove the last character from our word, and the return charcter to see if our user has pressed Enter.

Once enter has been pressed, return the word.

There is also a built in limit, where the user can only input as many characters as there are underscores, as this will cause letters to linger, you can always modify this by incrementing the number of underscores or something similar.

WINDOWS ONLY:

import msvcrt


def windows_get_input(prefix="", underscores=20, blank_char='_'):

    word = ""

    print(prefix + (underscores - len(word)) * blank_char, end='\r', flush=True)
    # Reprint prefix to move cursor
    print(prefix, end="", flush=True)

    while True:
        ch = msvcrt.getch()
        if ch in b'\x08':
            # Remove character if backspace
            word = word[:-1]
        elif ch in b'\r':
            # break if enter pressed
            break
        else:
            if len(word) == underscores:
                continue
            try:
                char = str(ch.decode("utf-8"))
            except:
                continue
            word += str(char)
        # Print `\r` to return to start of line and then print prefix, word and underscores.
        print('\r' + prefix + word + (underscores - len(word)) * blank_char, end='\r', flush=True)
        # Reprint prefix and word to move cursor
        print(prefix + word, end="", flush=True)
    print()
    return word

print(windows_get_input("Name: ", 20, '_'))

Handling both Windows and Unix

WINDOWS and UNIX:

def unix_getch():
    import termios
    import sys, tty
    def _getch():
        fd = sys.stdin.fileno()
        old_settings = termios.tcgetattr(fd)
        try:
            tty.setraw(fd)
            ch = sys.stdin.read(1)
        finally:
            termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
        return ch.encode("utf-8")
    return _getch()

def get_input(prefix="", underscores=20, blank_char='_'):

    word = ""

    try:
        import msvcrt
        func = msvcrt.getch
    except:
        func = unix_getch

    print(prefix + (underscores - len(word)) * blank_char, end='\r', flush=True)
    # Reprint prefix to move cursor
    print(prefix, end="", flush=True)

    while True:
        ch = func()
        if ch in b'\x08\x7f':
            # Remove character if backspace
            word = word[:-1]
        elif ch in b'\r':
            # break if enter pressed
            break
        else:
            if len(word) == underscores:
                continue
            try:
                char = str(ch.decode("utf-8"))
            except:
                continue
            word += str(char)
        # Print `\r` to return to start of line and then print prefix, word and underscores.
        print('\r' + prefix + word + (underscores - len(word)) * blank_char, end='\r', flush=True)
        # Reprint prefix and word to move cursor
        print(prefix + word, end="", flush=True)
    print()
    return word

print(get_input("Name: ", 20, '_'))

Handling IDLE

With IDLE, this fails. Thanks Python for giving us this... Anayway, if you want to handle running in IDLE, simply add the following at the top of the get_input() function:

    import sys

    if 'idlelib.run' in sys.modules:
        return input(prefix)

This will check if you are using IDLE and just prompt the user for input normally.

Solution 2:

Compose your prompt of text, a number of underscores, and then same number of backspace characters (\b).

n_underscores = 45
a = input('Enter your name:' + '_' * n_underscores + '\b' * n_underscores)
print('Hi,', a)

Solution 3:

You can use a \r character to return to the start of the line and overwrite text until you want the input cursor:

print("Enter your name: ____________________", end='\rEnter your name: ', flush=True)
a = input()

It is worth noting that moving a cursor only works in some consoles, for example, it will not work in IDLE, but it will work in windows command prompt