You know how in Linux when you try some Sudo stuff it tells you to enter the password and, as you type, nothing is shown in the terminal window (the password is not shown)?
Is there a way to do that in Python? I'm working on a script that requires so sensitive info and would like for it to be hidden when I'm typing it.
In other words, I want to get the password from the user without showing the password.
Use getpass.getpass():
from getpass import getpass
password = getpass()
An optional prompt can be passed as parameter; the default is "Password: ".
Note that this function requires a proper terminal, so it can turn off echoing of typed characters – see “GetPassWarning: Can not control echo on the terminal” when running from IDLE for further details.
import getpass
pswd = getpass.getpass('Password:')
getpass works on Linux, Windows, and Mac.
This code will print an asterisk instead of every letter.
import sys
import msvcrt
passwor = ''
while True:
x = msvcrt.getch()
if x == '\r':
break
sys.stdout.write('*')
passwor +=x
print '\n'+passwor
Updating on the answer of #Ahmed ALaa
# import msvcrt
import getch
def getPass():
passwor = ''
while True:
x = getch.getch()
# x = msvcrt.getch().decode("utf-8")
if x == '\r' or x == '\n':
break
print('*', end='', flush=True)
passwor +=x
return passwor
print("\nout=", getPass())
msvcrt us only for windows, but getch from PyPI should work for both (I only tested with linux).
You can also comment/uncomment the two lines to make it work for windows.
You can also use the pwinput module which works on both Windows and Linux.
It replaces the char with '*' (by default) and backspace works.
import pwinput
password = pwinput.pwinput(prompt='Password: ')
You can, optionally, pass a different mask character as well.
import pwinput
password = pwinput.pwinput(prompt='Password: ', mask='')
See the pwinput documentation for more information.
Here is my code based off the code offered by #Ahmed ALaa
Features:
Works for passwords up to 64 characters
Accepts backspace input
Outputs * character (DEC: 42 ; HEX: 0x2A) instead of the input character
Demerits:
Works on Windows only
The function secure_password_input() returns the password as a string when called. It accepts a Password Prompt string, which will be displayed to the user to type the password
def secure_password_input(prompt=''):
p_s = ''
proxy_string = [' '] * 64
while True:
sys.stdout.write('\x0D' + prompt + ''.join(proxy_string))
c = msvcrt.getch()
if c == b'\r':
break
elif c == b'\x08':
p_s = p_s[:-1]
proxy_string[len(p_s)] = " "
else:
proxy_string[len(p_s)] = "*"
p_s += c.decode()
sys.stdout.write('\n')
return p_s
Related
You know how in Linux when you try some Sudo stuff it tells you to enter the password and, as you type, nothing is shown in the terminal window (the password is not shown)?
Is there a way to do that in Python? I'm working on a script that requires so sensitive info and would like for it to be hidden when I'm typing it.
In other words, I want to get the password from the user without showing the password.
Use getpass.getpass():
from getpass import getpass
password = getpass()
An optional prompt can be passed as parameter; the default is "Password: ".
Note that this function requires a proper terminal, so it can turn off echoing of typed characters – see “GetPassWarning: Can not control echo on the terminal” when running from IDLE for further details.
import getpass
pswd = getpass.getpass('Password:')
getpass works on Linux, Windows, and Mac.
This code will print an asterisk instead of every letter.
import sys
import msvcrt
passwor = ''
while True:
x = msvcrt.getch()
if x == '\r':
break
sys.stdout.write('*')
passwor +=x
print '\n'+passwor
Updating on the answer of #Ahmed ALaa
# import msvcrt
import getch
def getPass():
passwor = ''
while True:
x = getch.getch()
# x = msvcrt.getch().decode("utf-8")
if x == '\r' or x == '\n':
break
print('*', end='', flush=True)
passwor +=x
return passwor
print("\nout=", getPass())
msvcrt us only for windows, but getch from PyPI should work for both (I only tested with linux).
You can also comment/uncomment the two lines to make it work for windows.
You can also use the pwinput module which works on both Windows and Linux.
It replaces the char with '*' (by default) and backspace works.
import pwinput
password = pwinput.pwinput(prompt='Password: ')
You can, optionally, pass a different mask character as well.
import pwinput
password = pwinput.pwinput(prompt='Password: ', mask='')
See the pwinput documentation for more information.
Here is my code based off the code offered by #Ahmed ALaa
Features:
Works for passwords up to 64 characters
Accepts backspace input
Outputs * character (DEC: 42 ; HEX: 0x2A) instead of the input character
Demerits:
Works on Windows only
The function secure_password_input() returns the password as a string when called. It accepts a Password Prompt string, which will be displayed to the user to type the password
def secure_password_input(prompt=''):
p_s = ''
proxy_string = [' '] * 64
while True:
sys.stdout.write('\x0D' + prompt + ''.join(proxy_string))
c = msvcrt.getch()
if c == b'\r':
break
elif c == b'\x08':
p_s = p_s[:-1]
proxy_string[len(p_s)] = " "
else:
proxy_string[len(p_s)] = "*"
p_s += c.decode()
sys.stdout.write('\n')
return p_s
how do I change the text to * while it is being inputted, like:
#Think that the code below is running in the console and I am
#inputting in it
Password: Example # How do make it turn it to '*******' while it is still being written?
Yup, i am not forced to only input, I can type in any command, please just tell me how to.
And you can tell tk code too
use the getpass module -
import getpass
getpass.getpass("Enter your password: ")
For tkinter entry, use the option show. Here is a code:
import tkinter as tk
root = tk.Tk()
passw = tk.Entry(root,show="*")
passw.grid(row=0,column=0)
passb = tk.Button(root,text="Print Password",command=lambda :print(passw.get()))
passb.grid(row=1,column=0)
root.mainloop()
To get password in console, you will have to modify the module getpass (Try at your own risk). Go to your python folder and open folder Lib. Open the file getpass.py and go to line 98 (there will be a function naming win_getpass)
Replace the whole function (win_getpass) with (lines:98-119) (Updated):
def win_getpass(prompt='Password: ', stream=None,show=""):
"""Prompt for password with echo off, using Windows getch()."""
if sys.stdin is not sys.__stdin__:
return fallback_getpass(prompt, stream)
for c in prompt:
msvcrt.putwch(c)
pw = ""
while True:
c = msvcrt.getwch()
if c == '\r' or c == '\n':
break
if c == '\003':
raise KeyboardInterrupt
if c == '\b':
pw = pw[:-1]
if pw != "":msvcrt.putwch("\b");msvcrt.putwch(" ");msvcrt.putwch("\b")
else:
pw = pw + c
msvcrt.putwch(show)
msvcrt.putwch('\r')
msvcrt.putwch('\n')
return pw
Now you can use the getpass function as:
import getpass
getpass.getpass("Enter your password: ",show="*")
You can change the value of show to whatever you want to show. Default is empty (means hide).
Note:
getpass will only work in console. It will raise error in IDLE.
Screenshot:
You know how in Linux when you try some Sudo stuff it tells you to enter the password and, as you type, nothing is shown in the terminal window (the password is not shown)?
Is there a way to do that in Python? I'm working on a script that requires so sensitive info and would like for it to be hidden when I'm typing it.
In other words, I want to get the password from the user without showing the password.
Use getpass.getpass():
from getpass import getpass
password = getpass()
An optional prompt can be passed as parameter; the default is "Password: ".
Note that this function requires a proper terminal, so it can turn off echoing of typed characters – see “GetPassWarning: Can not control echo on the terminal” when running from IDLE for further details.
import getpass
pswd = getpass.getpass('Password:')
getpass works on Linux, Windows, and Mac.
This code will print an asterisk instead of every letter.
import sys
import msvcrt
passwor = ''
while True:
x = msvcrt.getch()
if x == '\r':
break
sys.stdout.write('*')
passwor +=x
print '\n'+passwor
Updating on the answer of #Ahmed ALaa
# import msvcrt
import getch
def getPass():
passwor = ''
while True:
x = getch.getch()
# x = msvcrt.getch().decode("utf-8")
if x == '\r' or x == '\n':
break
print('*', end='', flush=True)
passwor +=x
return passwor
print("\nout=", getPass())
msvcrt us only for windows, but getch from PyPI should work for both (I only tested with linux).
You can also comment/uncomment the two lines to make it work for windows.
You can also use the pwinput module which works on both Windows and Linux.
It replaces the char with '*' (by default) and backspace works.
import pwinput
password = pwinput.pwinput(prompt='Password: ')
You can, optionally, pass a different mask character as well.
import pwinput
password = pwinput.pwinput(prompt='Password: ', mask='')
See the pwinput documentation for more information.
Here is my code based off the code offered by #Ahmed ALaa
Features:
Works for passwords up to 64 characters
Accepts backspace input
Outputs * character (DEC: 42 ; HEX: 0x2A) instead of the input character
Demerits:
Works on Windows only
The function secure_password_input() returns the password as a string when called. It accepts a Password Prompt string, which will be displayed to the user to type the password
def secure_password_input(prompt=''):
p_s = ''
proxy_string = [' '] * 64
while True:
sys.stdout.write('\x0D' + prompt + ''.join(proxy_string))
c = msvcrt.getch()
if c == b'\r':
break
elif c == b'\x08':
p_s = p_s[:-1]
proxy_string[len(p_s)] = " "
else:
proxy_string[len(p_s)] = "*"
p_s += c.decode()
sys.stdout.write('\n')
return p_s
You know how in Linux when you try some Sudo stuff it tells you to enter the password and, as you type, nothing is shown in the terminal window (the password is not shown)?
Is there a way to do that in Python? I'm working on a script that requires so sensitive info and would like for it to be hidden when I'm typing it.
In other words, I want to get the password from the user without showing the password.
Use getpass.getpass():
from getpass import getpass
password = getpass()
An optional prompt can be passed as parameter; the default is "Password: ".
Note that this function requires a proper terminal, so it can turn off echoing of typed characters – see “GetPassWarning: Can not control echo on the terminal” when running from IDLE for further details.
import getpass
pswd = getpass.getpass('Password:')
getpass works on Linux, Windows, and Mac.
This code will print an asterisk instead of every letter.
import sys
import msvcrt
passwor = ''
while True:
x = msvcrt.getch()
if x == '\r':
break
sys.stdout.write('*')
passwor +=x
print '\n'+passwor
Updating on the answer of #Ahmed ALaa
# import msvcrt
import getch
def getPass():
passwor = ''
while True:
x = getch.getch()
# x = msvcrt.getch().decode("utf-8")
if x == '\r' or x == '\n':
break
print('*', end='', flush=True)
passwor +=x
return passwor
print("\nout=", getPass())
msvcrt us only for windows, but getch from PyPI should work for both (I only tested with linux).
You can also comment/uncomment the two lines to make it work for windows.
You can also use the pwinput module which works on both Windows and Linux.
It replaces the char with '*' (by default) and backspace works.
import pwinput
password = pwinput.pwinput(prompt='Password: ')
You can, optionally, pass a different mask character as well.
import pwinput
password = pwinput.pwinput(prompt='Password: ', mask='')
See the pwinput documentation for more information.
Here is my code based off the code offered by #Ahmed ALaa
Features:
Works for passwords up to 64 characters
Accepts backspace input
Outputs * character (DEC: 42 ; HEX: 0x2A) instead of the input character
Demerits:
Works on Windows only
The function secure_password_input() returns the password as a string when called. It accepts a Password Prompt string, which will be displayed to the user to type the password
def secure_password_input(prompt=''):
p_s = ''
proxy_string = [' '] * 64
while True:
sys.stdout.write('\x0D' + prompt + ''.join(proxy_string))
c = msvcrt.getch()
if c == b'\r':
break
elif c == b'\x08':
p_s = p_s[:-1]
proxy_string[len(p_s)] = " "
else:
proxy_string[len(p_s)] = "*"
p_s += c.decode()
sys.stdout.write('\n')
return p_s
Following code prompts for user and password, when run in console:
import getpass
user = getpass.getpass("Username:")
passwd = getpass.getpass("Password for " + user + ":")
print "Got", user, passwd
The obvious problem with above is, user name is not echoed as it is typed.
Now getpass documentation says "On Unix it defaults to using /dev/tty before falling back to sys.stdin and sys.stderr."
Question: How to ask for both username and password, so that they are read from same source, and username is echoed normally, while password is not?
Why not just use raw_input for the username:
import getpass
user = raw_input("Username:")
passwd = getpass.getpass("Password for " + user + ":")
print("Got", user, passwd)
Demo:
Username:iCodez
Password for iCodez:
('Got', 'iCodez', 'secret')
There is another alternative, which I found documented here. Detect whether the input stream is a TTY, and change your input method based on that information.
I used something like this:
#!/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)
This works fine from a terminal:
bash> ./mytest.py
Enter credentials
Username: one
Password:
Username: [one], password [two]
for piped input:
bash> echo "one
> two" | ./mytest.py
Username: [one], password [two]
for input from a file:
bash> echo "one" > input
bash> echo "two" >> input
bash> ./mytest.py < input
Username: [one], password [two]
and also for a heredoc:
bash> ./mytest.py << EOF
> one
> two
> EOF
Username: [one], password [two]
Personally, that covers all of my needs.
In Python 2.x, use raw_input (input in Python 3.x) instead of getpass.getpass for username.
user = raw_input("Username:")
It would be possible to use raw_input (input in Python 3) but as already mentioned in the question, getpass is using /dev/tty before falling back to sys.stdin and sys.stderr. This means that in some situations getpass and raw_input is using different sources.
On linux, you might see the difference by executing the application with the following command:
my_app.py < /path/to/some/file
The function raw_input would read from the file while getpass would still use the terminal. Even if it is not documented explicitly, the same is happening on Windows.
I have not found a function that is doing something like getpass without hiding the input. I think you have to implement it yourself or search for a library which is doing it. You can look at the current implementation of getpass in Python 3 and in Python 2.7 to get some inspiration.
I wrote an exmaple below. Basically, I used the implementation of Python 3 and removed everything that is related to hiding the input. Then, I made some changes to support 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
I tested my implementation with Python 2.7 on Windows and with Python 2.7 and 3.5 on Arch Linux.
try this:
user = raw_input("Username:")