用星号屏蔽python中的用户输入
Posted
技术标签:
【中文标题】用星号屏蔽python中的用户输入【英文标题】:Masking user input in python with asterisks 【发布时间】:2015-02-22 06:15:16 【问题描述】:我试图用星号掩盖用户在 IDLE 中输入的内容,以便他们周围的人看不到他们正在输入/已输入的内容。我正在使用基本的原始输入来收集他们输入的内容。
key = raw_input('Password :: ')
用户输入密码后的理想 IDLE 提示:
Password :: **********
【问题讨论】:
你必须做一些自定义的标准输出重定向来用星号屏蔽,但是有一个更简单的方法来获取密码***.com/a/1761753/1268926 【参考方案1】:根据操作系统,如何从用户输入中获取单个字符以及如何检查回车符会有所不同。
看到这个帖子:Python read a single character from the user
例如,在 OSX 上,您可以这样做:
import sys, tty, termios
def getch():
fd = sys.stdin.fileno()
old_settings = termios.tcgetattr(fd)
try:
tty.setraw(sys.stdin.fileno())
ch = sys.stdin.read(1)
finally:
termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
return ch
key = ""
sys.stdout.write('Password :: ')
while True:
ch = getch()
if ch == '\r':
break
key += ch
sys.stdout.write('*')
print
print key
【讨论】:
【参考方案2】:为了解决这个问题,我编写了这个小模块pyssword 以在提示符下屏蔽用户输入密码。它适用于窗户。代码如下:
from msvcrt import getch
import getpass, sys
def pyssword(prompt='Password: '):
'''
Prompt for a password and masks the input.
Returns:
the value entered by the user.
'''
if sys.stdin is not sys.__stdin__:
pwd = getpass.getpass(prompt)
return pwd
else:
pwd = ""
sys.stdout.write(prompt)
sys.stdout.flush()
while True:
key = ord(getch())
if key == 13: #Return Key
sys.stdout.write('\n')
return pwd
break
if key == 8: #Backspace key
if len(pwd) > 0:
# Erases previous character.
sys.stdout.write('\b' + ' ' + '\b')
sys.stdout.flush()
pwd = pwd[:-1]
else:
# Masks user input.
char = chr(key)
sys.stdout.write('*')
sys.stdout.flush()
pwd = pwd + char
【讨论】:
在 Linux/MacOS 上测试过吗?【参考方案3】:免责声明:在终端中不提供星号,但在 jupyter 笔记本中提供。
下面的代码提供了用星号替换书写字符并允许删除错误输入的字符。星号的数量反映了输入字符的数量。
import getpass
key = getpass.getpass('Password :: ')
用户按下回车后:
【讨论】:
虽然您的代码 sn-p 可能会解决问题,但您应该描述您的代码的目的是什么(它如何解决问题)。此外,您可能需要检查***.com/help/how-to-answer 在终端或命令行上运行时,getpass
完全隐藏输入。不显示星号。【参考方案4】:
如果您想要一个适用于 Windows/macOS/Linux 和 Python 2 和 3 的解决方案,您可以安装 stdiomask
模块:
pip install stdiomask
与getpass.getpass()
(在 Python 标准库中)不同,stdiomask
模块可以在您键入时显示 *** 掩码字符。
示例用法:
>>> stdiomask.getpass()
Password: *********
'swordfish'
>>> stdiomask.getpass(mask='X') # Change the mask character.
Password: XXXXXXXXX
'swordfish'
>>> stdiomask.getpass(prompt='PW: ', mask='*') # Change the prompt.
PW: *********
'swordfish'
>>> stdiomask.getpass(mask='') # Don't display anything.
Password:
'swordfish'
不幸的是,这个模块,就像 Python 的内置 getpass
模块一样,在 IDLE 或 Jupyter Notebook 中不起作用。
更多详情https://pypi.org/project/stdiomask/
【讨论】:
这对我使用 Python 3.7 的 PyCharm 控制台不起作用,但 getpass.getpass 也不起作用。两者都只使用输入之类的东西。这似乎是 PyCharm 的限制,而不是您的库的问题。 请问有没有办法让它在 Jupyter notebook 中工作? 不幸的是,它无法在 Jupyter notebook 中运行。它与命令行/终端窗口非常相关,因此在浏览器(如 Jupyter)中运行或提供其自己的文本输出屏幕(如 VS Code)的系统不会执行以命令方式擦除文本的终端控制代码行窗口会。 谢谢。对于 IDLE 来说似乎是同样的问题,它会回显并显示密码。 次要注意:stdiomask 现在称为 pwinput。你会运行import pwinput
,然后调用pwinput.pwinput()
【参考方案5】:
我在尝试执行相同的壮举时偶然发现了这个线程。我知道这个帖子很旧,但如果其他人需要这个 - 这就是我的做法。
我最终使用了readchar 包。
这是我的解决方案,它打印星号并处理退格:
import sys, readchar
def passprompt(prompt: str, out = sys.stdout) -> str:
out.write(prompt); out.flush()
password = ""
while True:
ch = str(readchar.readchar(), encoding='UTF-8')
if ch == '\r':
break
elif ch == '\b':
out.write('\b \b')
password = password[0:len(password)-1]
out.flush()
else:
password += ch
out.write('*')
out.flush()
return password
我必须定期刷新标准输出才能正常工作。
【讨论】:
【参考方案6】:我的建议是——不要这样做!
不要重新发明***,如果你想要“星星”,请使用密码助手
见https://***.com/a/67327327/701532
【讨论】:
以上是关于用星号屏蔽python中的用户输入的主要内容,如果未能解决你的问题,请参考以下文章
如果用户输入“*”则添加 1,如果用户输入“”则添加 0 到 C 中的数组