31

I am trying to figure out how to suppress the display of user input on stdout.

raw_input() followed by any print statement preserves what the user typed in. getpass() does not show what the user typed, but it does preserve the "Password:" prompt.

To fix this, I would like to only remove the last line (which would remove the newline from the end of the line as well).

javanix
  • 1,270
  • 3
  • 24
  • 40

5 Answers5

47

You might be able to do what you want with VT100 control codes.

Something like this maybe:

CURSOR_UP_ONE = '\x1b[1A'
ERASE_LINE = '\x1b[2K'
print(CURSOR_UP_ONE + ERASE_LINE)
Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
  • 12
    `print(CURSOR_UP_ONE + ERASE_LINE + CURSOR_UP_ONE)` did the trick for me. – Dr. Jan-Philip Gehrcke Sep 25 '12 at 16:20
  • Yes, this works for me. Thanks much! Unfortunately if the input to STDIN doesn't come from the keyboard then it ends up clearing too many lines though. – javanix Sep 25 '12 at 17:22
  • 1
    @javanix If on a UNIX machine (OSX or Linux) then you can use [`os.isatty`](http://docs.python.org/library/os.html#os.isatty) to check if `STDIN` is a console or not. Might be something similar for Windows but I don't know about it. – Some programmer dude Sep 25 '12 at 17:35
  • to erase the line `"\x1b[2K"` didn't work but `"\x1b[1M"` worked. After hours of searching, I could only find that command [here](https://github.com/adoxa/ansicon#sequences) – Rui Botelho Oct 29 '14 at 21:44
  • 2
    @RuiBotelho It depends very much on the terminal type used. The Windows command prompt window, for example, is known for not handling VT100 escape sequences, or just a very limited subset of them. Any Linux or OSX terminal, on the other hand, should have very good implementation of them. – Some programmer dude Oct 30 '14 at 07:49
  • @JoachimPileborg I found this sequence can only handle 23 lines. Would you please answer my question here: http://stackoverflow.com/questions/35267489/python-vt100-sequences-can-only-handle-23-lines-on-osxs-terminal – spacegoing Feb 08 '16 at 10:42
  • This works in linux bash, but isn't working on Windows' Powershell – polortiz40 Feb 28 '21 at 01:36
3

Give this a try:

CURSOR_UP = '\033[F'
ERASE_LINE = '\033[K'
print(CURSOR_UP + ERASE_LINE)
Ohad Cohen
  • 5,756
  • 3
  • 39
  • 36
1

I am not entirely sure if this works: maybe you could, just before calling raw_input(), replace sys.stdout with your self-defined file-like object which swallows the output. Right after that, you could set sys.stdout back to what it has been before.

Edit: looks like this approach does not work, because whatever the user types in stays on the screen.

Another option for console manipulation and direct keyboard control is curses.

Dr. Jan-Philip Gehrcke
  • 33,287
  • 14
  • 85
  • 130
1

If what you're doing is reading a password, use getpass. There are a lot of subtle gotchas involved in reading a password safely; it's not code you want to write yourself.

If you are doing something less security-critical, disabling terminal echo can be done with the termios module. (I wish the example code there wasn't an incomplete, unsafe implementation of getpass, sigh. But it does show you how to turn off terminal echo.)

If you're on Windows, there is an equivalent but I don't know what it is, and it may not be exposed in the Python standard library.

zwol
  • 135,547
  • 38
  • 252
  • 361
1

The following code, based on the Python docs, uses the termios module and seems to do what you want (although it is not as compact as VT100 control codes):

def getpass(prompt="Password: "):
    import termios, sys
    fd = sys.stdin.fileno()
    old = termios.tcgetattr(fd)
    new = termios.tcgetattr(fd)
    new[3] = new[3] & ~termios.ECHO
    try:
        termios.tcsetattr(fd, termios.TCSADRAIN, new)
        passwd = raw_input(prompt)
        print '\r          \r',
    finally:
        termios.tcsetattr(fd, termios.TCSADRAIN, old)
    return passwd

p = getpass()

There are two tricky lines: one disables the echo, the other one erases your password prompt remaining at the first position of the line.

Vicent
  • 5,322
  • 2
  • 28
  • 36