在代码中提示输入用户名和密码时,在控制台中运行:
import getpass
user = getpass.getpass("Username:")
passwd = getpass.getpass("Password for " + user + ":")
print "Got", user, passwd
上面显而易见的问题是,用户名在键入时不会回显。
现在getpass
documentation说“在Unix上它默认使用/ dev / tty然后再回到sys.stdin和sys.stderr。”
问题:如何同时询问用户名和密码,以便从同一来源读取,并且用户名正常回显,而密码不是?
答案 0 :(得分:15)
为什么不使用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')
答案 1 :(得分:10)
使用raw_input
代替getpass.getpass
用户名。
user = raw_input("Username:")
答案 2 :(得分:3)
可以在Python 3中使用raw_input
(input
),但正如问题中已经提到的,getpass
在回退到sys.stdin之前使用/ dev / tty和sys.stderr。这意味着在某些情况下getpass
和raw_input
使用不同的来源。
在linux上,您可能会通过使用以下命令执行应用程序来看到差异:
my_app.py < /path/to/some/file
函数raw_input
将从文件中读取,而getpass
仍将使用终端。即使没有明确记录,Windows上也会发生同样的情况。
我没有找到一个像getpass
这样的函数而没有隐藏输入。我认为你必须自己实现它或者搜索正在这样做的库。您可以查看getpass
in Python 3和in Python 2.7的当前实施情况,以获得一些灵感。
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
我在Windows上使用Python 2.7以及在Arch Linux上使用Python 2.7和3.5测试了我的实现。
答案 3 :(得分:3)
还有另一种选择,我找到了here。检测输入流是否为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]
以及heredoc:
bash> ./mytest.py << EOF
> one
> two
> EOF
Username: [one], password [two]
就个人而言,这涵盖了我的所有需求。
答案 4 :(得分:1)
试试这个:
user = raw_input("Username:")