S
Steven D'Aprano
I have a function which reads characters from stdin and writes stars to
stdout, but backspacing does not erase the stars as I expected.
Tested in Python 2.6 on Linux. This will almost certainly not work on
Windows.
import sys, tty, termios
def getpass():
fd = sys.stdin.fileno()
old_settings = termios.tcgetattr(fd)
chars = []
try:
tty.setraw(sys.stdin.fileno())
while 1:
c = sys.stdin.read(1)
if c in '\n\r': # Enter or Return key.
break
elif c == '\x7f': # Backspace key.
if chars:
# Rubout previous character.
sys.stdout.write('\b')
sys.stdout.flush()
del chars[-1]
else:
# Obfuscate the letter typed.
sys.stdout.write('*')
chars.append(c)
finally:
termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
sys.stdout.write('\n')
return ''.join(chars)
When I call this function and then type, I get a serious of asterisks as
expected. Each time I press the backspace key, the cursor moves one
character to the left, but the asterisks remain visible.
Is there a way to erase the character other than backspacing, writing a
space, then backspacing again? That feels inelegant.
stdout, but backspacing does not erase the stars as I expected.
Tested in Python 2.6 on Linux. This will almost certainly not work on
Windows.
import sys, tty, termios
def getpass():
fd = sys.stdin.fileno()
old_settings = termios.tcgetattr(fd)
chars = []
try:
tty.setraw(sys.stdin.fileno())
while 1:
c = sys.stdin.read(1)
if c in '\n\r': # Enter or Return key.
break
elif c == '\x7f': # Backspace key.
if chars:
# Rubout previous character.
sys.stdout.write('\b')
sys.stdout.flush()
del chars[-1]
else:
# Obfuscate the letter typed.
sys.stdout.write('*')
chars.append(c)
finally:
termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
sys.stdout.write('\n')
return ''.join(chars)
When I call this function and then type, I get a serious of asterisks as
expected. Each time I press the backspace key, the cursor moves one
character to the left, but the asterisks remain visible.
Is there a way to erase the character other than backspacing, writing a
space, then backspacing again? That feels inelegant.