Как отобразить текст, который вводит пользователь, как другой символ в Python 3?

Я пытаюсь создать программу имени пользователя и пароля на Python, и хотя это не обязательно для окончательной программы, я подумал, что было бы неплохо заставить ее отображать другой символ при вводе текста. Как и большинство полей пароля, которые могут отображать что-то вроде звездочки (*). Поэтому мне было интересно, как я могу отображать их ввод как другой символ. Спасибо за любую помощь :)


person Michael Hopper    schedule 04.02.2016    source источник
comment
используйте модуль getpass   -  person Paulo Scardine    schedule 04.02.2016
comment
Вы должны прочитать пароль с tty (чтобы вы могли отключить эхо символов) и записать свой * на стандартный вывод или на tty   -  person Andrea Corbellini    schedule 04.02.2016
comment
@Paulo Scardine Я пытаюсь сделать так, чтобы моя программа проверяла имя пользователя и пароль как забавный проект, это лишило бы смысла то, что я делаю: P   -  person Michael Hopper    schedule 04.02.2016
comment
На самом деле то, что я написал, может быть неверным: пока эхо отключено, написанные символы не будут отображаться. Я не думаю, что существует безопасный способ   -  person Andrea Corbellini    schedule 04.02.2016


Ответы (1)


Используя рецепт getch из вопроса " Python прочитал один символ от пользователя "

def getpass(prompt):
    sys.stdout.write(prompt)
    sys.stdout.flush()
    password = ''
    while True:
        c = getch()
        if c == '\r':
            sys.stdout.write('\n')
            sys.stdout.flush()
            return password
        password += c
        sys.stdout.write('*')
        sys.stdout.flush()

Доказательство:

>>> getpass('secret: ')
secret: ********
'asdfsafd'

Отображение * для каждого введенного символа может показаться крутым с точки зрения пользовательского интерфейса, но немного поставит под угрозу безопасность, потому что это дает длину пароля. Я думаю, именно поэтому встроенный модуль getpass ничего не будет повторять.

[Обновить]

По словам Андреа Корбеллини, эта реализация приведет к утечке нажатий клавиш, если система находится под большой нагрузкой, потому что она сбрасывает tty перед возвратом — символы могут отображаться после возврата getch() и до повторного вызова getch(). Похоже, это очень сложно сделать безопасным способом, поэтому, вероятно, это причина, по которой встроенный getpass не обеспечивает визуальную обратную связь для каждого нажатия клавиши.

person Paulo Scardine    schedule 04.02.2016
comment
Не знаю насчет Windows, но в UNIX это решение зависит от условий гонки: если вы набираете символ во время выполнения if c == '\r' ... password += c ; sys.stdout.write('*') ..., то символ будет отображаться - person Andrea Corbellini; 04.02.2016
comment
@AndreaCorbellini Вы уверены? Здесь мы не используем асинхронный ввод-вывод, getch блокирует. Если вы можете вызвать эту ошибку, не могли бы вы опубликовать воспроизводимый случай? - person Paulo Scardine; 04.02.2016
comment
Проблема не в том, когда getch работает, а когда он не работает. Попробуйте поставить for i in range(100000): pass после вызова getch() (для имитации медленного кода или высокой загрузки процессора) и запустите скрипт, удерживая нажатой a. Вы увидите чередование символов * и a на терминале. - person Andrea Corbellini; 04.02.2016
comment
Используемая вами реализация getch() сбрасывает tty перед возвратом. Таким образом, символы могут отображаться после возврата getch() и до повторного вызова getch(). - person Andrea Corbellini; 04.02.2016
comment
Спасибо. Я предполагаю, что это достаточно сложно спровоцировать, чтобы ОП мог использовать его на практике, если он берет на себя риск повторения некоторых нажатий клавиш, когда система находится под большой нагрузкой. - person Paulo Scardine; 04.02.2016