可以使用raw_input
(input
在 Python 3 中),但正如问题中已经提到的,getpass
在回退到 sys.stdin 和 sys.stderr 之前使用 /dev/tty。这意味着在某些情况下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
我在 Windows 上使用 Python 2.7 以及在 Arch Linux 上使用 Python 2.7 和 3.5 测试了我的实现。