9

I'm developing a backup daemon that will run silently in the background. The daemon relies on the duplicity backup software, which when backing up requires an encryption key. I cannot ask for the password through the console because obviously, the daemon has no access to such.

How could I easily create a prompt that asks the user to type in a password, and returns it to the application (through a Python variable)? I'm using Python 2.7.

2
  • Can you use TkInter or PyQt? Commented Mar 30, 2013 at 23:34
  • Yes, I'm not too worried about extra dependencies. Commented Mar 30, 2013 at 23:36

5 Answers 5

36

Because you asked for the simplest (Python 2.7):

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

For Python 3.3:

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

For Python 3.6+:

import tkinter as tk
import tkinter.simpledialog
tk.Tk().withdraw()
tkinter.simpledialog.askstring("Password", "Enter password:", show='*')
Sign up to request clarification or add additional context in comments.

2 Comments

For Python 3.3: import tkinter tkinter.simpledialog.askstring("Password", "Enter password:", show='*')
Seems only to work, if you initialize Tk() first, without it fails with 'NoneType' object has no attribute 'winfo_viewable'. At least in Python 3.6
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

5 Comments

Doesn't work for me. I fixed an issue with root being referenced before defined. Now I can get the dialog to show, but when I type the password 1) the characters show, instead of black dots and 2) when I hit return nothing is returned from getpwd. Also, I get an error when I click OK - onpwdentry() takes exactly 1 argument Thanks for the quick response.
Ok, that last edit should fix your problems. For 1) I set the "show" property of the Entry widget to '*', so it'll show asterisks instead of letters. 2) was an incredibly stupid error on my part: I had the subfunction returning the password, when I obviously wanted the main function returning it. mainloop() is blocking, so the password won't be returned until the window is destroyed by onokclick() or onpwdentry()
Thanks, just fixed the last bug, which was modifying the password outside its scope, which meant that the method was still returning "". Added a nonlocal hack for Python 2.x (using dict), and it successfully works!
Glad to help! Sorry about all the errors the first two edits; I don't seem to be thinking too well tonight.
@pycoder112358 still scoping issue are there i have updated with procedure at the bottom
5

Because not everyone wants to use TK, here's a script using PyQt:

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

And, because you wouldn't usually just ask a user for a password just for the heck of it:

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

And the corresponding bash function:

#!/bin/bash

passwordPrompt.py | tee

Comments

3

Resolved scoping issues of @pycoder112358 post:

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

1 Comment

You only need to use global inside onpwdentry() and onokclick().
3

Expanding on Diego's answer with some minimal housekeeping (without this I was getting crashes galore trying to use his beautifully brief example):

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!

This will work well from a program that is otherwise just a terminal / console application.

1 Comment

For me this is the best solution since I'm having a console application. But how to open the dialog window on the main screen, when having multiple screens on Linux? The solution from @pycoder112358 opens the dialog on the main screen.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.