使用Python中的图形对话框询问用户密码的最简单方法是什么?

9
我正在开发一个后台运行的备份守护程序。该守护程序依赖于备份软件,在备份时需要加密密钥。由于守护进程无法访问控制台,因此我无法通过控制台询问密码。
我该如何轻松地创建提示框要求用户输入密码,并将其返回给应用程序(通过Python变量)?我使用的是Python 2.7。

你能使用 TkInter 或 PyQt 吗? - chrisaycock
是的,我不太担心额外的依赖关系。 - liamzebedee
5个回答

35

因为你要求最简单的(Python 2.7):

import Tkinter, tkSimpleDialog
tkSimpleDialog.askstring("Password", "Enter password:", show='*')

对于Python 3.3版本:

import tkinter
tkinter.simpledialog.askstring("Password", "Enter password:", show='*')

对于 Python 3.6+:

import tkinter as tk
import tkinter.simpledialog
tk.Tk().withdraw()
tkinter.simpledialog.askstring("Password", "Enter password:", show='*')

1
对于Python 3.3: 导入tkinter tkinter.simpledialog.askstring("密码", "输入密码:", show='*') - ryry1985
4
似乎只有在先初始化Tk()的情况下,它才能正常工作,否则会出现“'NoneType' object has no attribute 'winfo_viewable'”错误。至少在Python 3.6中是这样。 - Andreas H.

5
from Tkinter import *

def getpwd():
    password = ''
    root = Tk()
    pwdbox = Entry(root, show = '*')
    def onpwdentry(evt):
         password = pwdbox.get()
         root.destroy()
    def onokclick():
         password = pwdbox.get()
         root.destroy()
    Label(root, text = 'Password').pack(side = 'top')

    pwdbox.pack(side = 'top')
    pwdbox.bind('<Return>', onpwdentry)
    Button(root, command=onokclick, text = 'OK').pack(side = 'top')

    root.mainloop()
    return password

对我来说不起作用。我修复了一个根引用在定义之前的问题。现在我可以让对话框显示出来,但是当我输入密码时,1)字符会显示,而不是黑点,2)当我按回车键时,getpwd中没有返回任何内容。此外,当我点击确定时,我会收到一个错误-onpwdentry()只需要一个参数。感谢您的快速回复。 - liamzebedee
好的,最后一次编辑应该解决了你的问题。对于 1),我将 Entry 组件的“show”属性设置为“*”,这样它会显示星号而不是字母。2)是我非常愚蠢的错误:我让子函数返回密码,而我显然想让主函数返回它。mainloop() 是阻塞的,因此只有在 onokclick() 或 onpwdentry() 销毁窗口时才会返回密码。 - pycoder112358
谢谢,我刚刚修复了最后一个bug,它修改了密码的作用域,这意味着该方法仍然返回“”。我为Python 2.x添加了一个非本地hack(使用字典),现在它成功运行! - liamzebedee
很高兴能帮忙!对于前两次编辑中的所有错误感到抱歉;今晚我的思维似乎不太清晰。 - pycoder112358
@pycoder112358,仍然存在作用域问题,我已经在底部更新了过程。 - Mallikarjunarao Kosuri

5

因为不是每个人都想使用TK,所以这里提供一个使用PyQt的脚本:

from PyQt5.QtWidgets import QApplication, QInputDialog, QLineEdit
import sys
app = QApplication(sys.argv)
qd = QInputDialog()
qd.setTextEchoMode(QLineEdit.Password)
qd.show()
app.exec()

因为通常不会仅仅为了玩乐而要求用户输入密码:

#!/bin/env python3
#passwordPrompt.py

from PyQt5.QtWidgets import QApplication, QInputDialog
import sys, time

def succFunc():
  sys.stdout.write(qd.textValue())
  sys.stdout.flush()
  exit(0)

def failFunc():
  exit(1)

app = QApplication(sys.argv)
qd = QInputDialog()
#QLineEdit.Password
qd.setTextEchoMode(2)
qd.rejected.connect(failFunc)
qd.accepted.connect(succFunc)
qd.show()
app.exec()

对应的Bash函数:

#!/bin/bash

passwordPrompt.py | tee

3

解决了@pycoder112358发布帖子的作用域问题:

from tkinter import *

PASSWORD = ''

def get_passwd():
    global PASSWORD
    root = Tk()
    pwdbox = Entry(root, show = '*')

    def onpwdentry(evt):
        global PASSWORD 
        PASSWORD = pwdbox.get()
        root.destroy()
    def onokclick():     
        global PASSWORD
        PASSWORD = pwdbox.get()
        root.destroy()

    Label(root, text = 'Password').pack(side = 'top')

    pwdbox.pack(side = 'top')
    pwdbox.bind('<Return>', onpwdentry)
    Button(root, command=onokclick, text = 'OK').pack(side = 'top')

    root.mainloop()
    return PASSWORD

你只需要在 onpwdentry()onokclick() 函数中使用全局变量。 - Pedro Lobito

3
扩展Diego的答案,进行了一些最小的整理(没有这些我试图使用他美丽简洁的示例时会频繁崩溃):
import Tkinter, tkSimpleDialog 
root = Tkinter.Tk() # dialog needs a root window, or will create an "ugly" one for you
root.withdraw() # hide the root window
password = tkSimpleDialog.askstring("Password", "Enter password:", show='*', parent=root)
root.destroy() # clean up after yourself!

这在一个仅仅是终端/控制台应用程序的情况下能够良好执行。

对我来说,这是最好的解决方案,因为我有一个控制台应用程序。但是,在Linux上有多个屏幕时,如何在主屏幕上打开对话框窗口呢?@pycoder112358的解决方案可以在主屏幕上打开对话框。 - eztam

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接