2013-10-29 9 views
5

folgenden Code Echo Eingabeaufforderungen für Benutzer und Kennwort ein, wenn in der Konsole ausführen:Python-Prompt für Benutzer mit Echo und Passwort ohne

import getpass 

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

print "Got", user, passwd 

Das offensichtliche Problem mit oben heißt, Benutzername nicht hallte wie er eingegeben wird.

Jetzt getpass documentation sagt "Auf Unix verwendet es standardmäßig/dev/tty vor dem Zurückfallen zu sys.stdin und sys.stderr."

Frage: Wie sowohl für Benutzername und Passwort fragen, so dass sie aus derselben Quelle gelesen werden, und Benutzername ist in der Regel hallt, während Kennwort nicht ist?

Antwort

9

Warum nicht einfach raw_input für den Benutzernamen verwenden:

import getpass 

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

print("Got", user, passwd) 

Demo:

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

Ich denke, das könnte die Frage nicht richtig beantworten. Wie in der Frage geschrieben, sagt die Dokumentation von "getpass" * "Unter Unix verwendet es standardmäßig/dev/tty, bevor es auf sys.stdin und sys.stderr zurückfällt" *. Sie werden den Unterschied zwischen "raw_input" und "getpass" sehen, wenn Sie Ihr Programm unter linux: './my_program.py JojOatXGME

8

Verwenden Sie raw_input anstelle von getpass.getpass für Benutzername.

user = raw_input("Username:") 
1

versuchen Sie dies:

user = raw_input("Username:") 
3

Es wäre möglich, raw_input zu verwenden (input in Python 3) aber wie bereits in der Frage erwähnt, verwendet getpass/dev/tty vor dem Zurückfallen auf sys.stdin und sys.stderr. Dies bedeutet, dass in bestimmten Situationen getpass und raw_input unterschiedliche Quellen verwenden.

Unter Linux können Sie den Unterschied durch Ausführen der Anwendung mit folgendem Befehl finden Sie unter:

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

Die Funktion raw_input aus der Datei lesen würde, während getpass noch das Terminal verwenden würde. Auch wenn dies nicht explizit dokumentiert ist, passiert das Gleiche unter Windows.


Ich habe keine Funktion, die tut so etwas wie getpass ohne Ausblenden der Eingang gefunden. Ich denke, du musst es selbst implementieren oder nach einer Bibliothek suchen, die das tut. Sie können die aktuelle Implementierung von getpassin Python 3 und in Python 2.7 betrachten, um etwas Inspiration zu bekommen.

Ich schrieb ein Beispiel unten. Im Grunde habe ich die Implementierung von Python 3 verwendet und alles entfernt, was mit dem Verstecken der Eingabe zusammenhängt. Dann habe ich einige Änderungen Python zu unterstützen 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 

Getestet habe ich meine Implementierung mit Python 2.7 unter Windows und mit Python 2.7 und 3.5 auf Arch Linux.

1

Es gibt eine andere Alternative, die ich dokumentierte here gefunden habe. Ermitteln Sie, ob der Eingabestream ein TTY ist, und ändern Sie Ihre Eingabemethode basierend auf diesen Informationen.

habe ich so etwas wie diese:

#!/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) 

Dies funktioniert gut von einem Terminal:

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

für verrohrt Eingang:

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

für die Eingabe aus einer Datei:

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

und auch für eine heredoc:

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

persönlich, dass deckt alle meine Bedürfnisse.

Verwandte Themen