Запрос Python для пользователя с эхом и паролем без эха

Следуя подсказкам кода для пользователя и пароля, при запуске в консоли:

import getpass

user = getpass.getpass("Username:")
passwd = getpass.getpass("Password for " + user + ":")

print "Got", user, passwd

Очевидная проблема, описанная выше, заключается в том, что имя пользователя не отражается по мере ее ввода.

Теперь getpass документации: "В Unix по умолчанию используется /dev/tty, прежде чем вернуться к sys.stdin и sys.stderr".

Вопрос: Как задать имя пользователя и пароль, чтобы они были прочитаны из одного источника, а имя пользователя выбрано нормально, а пароль - нет?

Ответы

Ответ 1

Есть еще одна альтернатива, которую я нашел задокументированной здесь. Определите, является ли поток ввода TTY, и измените метод ввода на основе этой информации.

Я использовал что-то вроде этого:

#!/usr/bin/python

import sys
import getpass

if sys.stdin.isatty():
   print "Enter credentials"
   username = raw_input("Username: ")
   password = getpass.getpass("Password: ")
else:
   username = sys.stdin.readline().rstrip()
   password = sys.stdin.readline().rstrip()

print "Username: [%s], password [%s]" % (username, password)

Это нормально работает с терминала:

bash> ./mytest.py
Enter credentials
Username: one
Password:
Username: [one], password [two]

для ввода по каналу:

bash> echo "one
> two" | ./mytest.py
Username: [one], password [two]

для ввода из файла:

bash> echo "one" > input
bash> echo "two" >> input
bash> ./mytest.py < input
Username: [one], password [two]

а также для наследственника:

bash> ./mytest.py << EOF
> one
> two
> EOF
Username: [one], password [two]

Лично это покрывает все мои потребности.

Ответ 2

Почему бы просто не использовать raw_input для имени пользователя:

import getpass

user = raw_input("Username:")
passwd = getpass.getpass("Password for " + user + ":")

print("Got", user, passwd)

Демо-версия:

Username:iCodez
Password for iCodez:
('Got', 'iCodez', 'secret')

Ответ 3

В Python 2.x используйте raw_input (input в Python 3.x) вместо getpass.getpass для имени пользователя.

user = raw_input("Username:")

Ответ 4

Можно было бы использовать raw_input (input в Python 3), но, как уже упоминалось в вопросе, getpass использует /dev/tty, прежде чем вернуться к sys.stdin и sys.stderr. Это означает, что в некоторых ситуациях getpass и raw_input используют разные источники.

В linux вы можете увидеть разницу, выполнив приложение с помощью следующей команды:

my_app.py < /path/to/some/file

Функция raw_input будет считывать из файла, а getpass все равно будет использовать терминал. Даже если это не задокументировано явно, то же самое происходит и в Windows.


Я не нашел функцию, которая делает что-то вроде getpass без скрытия ввода. Я думаю, вы должны реализовать его самостоятельно или искать библиотеку, которая это делает. Вы можете посмотреть текущую реализацию getpass в Python 3 и Python 2.7, чтобы получить вдохновение.

Я написал текст ниже. В основном, я использовал реализацию Python 3 и удалил все, что связано со скрытием ввода. Затем я внес некоторые изменения в поддержку Python 2.

def _raw_input(prompt, fin, fout):
    if prompt:
        try:
            fout.write(prompt)
        except UnicodeEncodeError:
            # Replace characters that are not supported by the terminal
            prompt = prompt.encode(fout.encoding, 'replace')
            prompt = prompt.decode(fout.encoding)
            fout.write(prompt)
        fout.flush()

    line = fin.readline()
    return line[:-1] if line[-1] == '\n' else line

def _ttyinput_unix(prompt):
    try:
        fd = os.open("/dev/tty", os.O_RDWR, os.O_NOCTTY)
        if sys.version_info < (3, 0):
            with os.fdopen(fd, 'w+', 1) as tty:
                return _raw_input(prompt, tty, tty)
        with io.FileIO(fd, 'w+') as tty:
            with io.TextIOWrapper(tty) as wrapper:
                return _raw_input(prompt, wrapper, wrapper)
    except (OSError, AttributeError) as e:
        return _raw_input(prompt, sys.stdin, sys.stderr)

def _ttyinput_win(prompt):
    if sys.stdin is not sys.__stdin__:
        # I don't know why getpass is doing this.
        return _raw_input(prompt, sys.stdin, sys.stderr)

    if sys.version_info >= (3, 0):
        getch = msvcrt.getwch
        putch = msvcrt.putwch
    else:
        getch = msvcrt.getch
        putch = msvcrt.putch

    for c in prompt:
        putch(c)

    password = ""
    while True:
        c = getch()
        if c == '\r' or c == '\n':
            break
        if c == '\003':
            raise KeyboardInterrupt
        if c == '\b':
            if len(password) > 0:
                password = password[:-1]
                for x in "\b \b":
                    putch(x)
        else:
            password += c
            putch(c)
    putch('\r')
    putch('\n')

    return password

try:
    import msvcrt
    ttyinput = _ttyinput_win
except ImportError:
    ttyinput = _ttyinput_unix

Я протестировал свою реализацию с Python 2.7 на Windows и с Python 2.7 и 3.5 на Arch Linux.

Ответ 5

попробуй это:

user = raw_input("Username:")