How do I convert a password into asterisks while it is being entered?

前端 未结 9 1948
感情败类
感情败类 2020-11-28 13:31

Is there a way in Python to convert characters as they are being entered by the user to asterisks, like it can be seen on many websites?

For example, if an email use

相关标签:
9条回答
  • 2020-11-28 14:00

    You can do this:

    # if getch module is available, then we implement our own getpass() with asterisks,
    # otherwise we just use the plain boring getpass.getpass()
    try:
        import getch
        def getpass(prompt):
            """Replacement for getpass.getpass() which prints asterisks for each character typed"""
            print(prompt, end='', flush=True)
            buf = ''
            while True:
                ch = getch.getch()
                if ch == '\n':
                    print('')
                    break
                else:
                    buf += ch
                    print('*', end='', flush=True)
            return buf
    except ImportError:
        from getpass import getpass
    
    0 讨论(0)
  • 2020-11-28 14:03

    You may want to check getpass function.

    Prompt the user for a password without echoing. The user is prompted using the string prompt, which defaults to 'Password: '. On Unix, the prompt is written to the file-like object stream. stream defaults to the controlling terminal (/dev/tty) or if that is unavailable to sys.stderr (this argument is ignored on Windows).

    Note: This module mimics unix password prompts and does not show asterisks.

    Usage:

    import getpass
    getpass.getpass()
    
    0 讨论(0)
  • 2020-11-28 14:07

    If you're using Tkinter: (this is Python 2.x. However, 3.x would be very similar)

    from Tkinter import Entry, Tk
    
    master = Tk()
    
    Password = Entry(master, bd=5, width=20, show="*")
    Password.pack()
    
    master.mainloop()
    

    In the shell, this is not possible. You can however write a function to store the entered text and report only a string of *'s when called. Kinda like this, which I did not write. I just Googled it.

    0 讨论(0)
  • 2020-11-28 14:07

    For anyone who would actually want to have asterisks appear, here's an improvement on Tigran Aivazian's answer. This version imports the built-in msvcrt.getch, adds cases for different line endings when hitting 'Enter/Return', and includes logic to support Backspace, as well as Ctrl+C (KeyboardInterrupt):

    try:
        from msvcrt import getch
        def getpass(prompt):
            """Replacement for getpass.getpass() which prints asterisks for each character typed"""
            print(prompt, end='', flush=True)
            buf = b''
            while True:
                ch = getch()
                if ch in {b'\n', b'\r', b'\r\n'}:
                    print('')
                    break
                elif ch == b'\x08': # Backspace
                    buf = buf[:-1]
                    print(f'\r{(len(prompt)+len(buf)+1)*" "}\r{prompt}{"*" * len(buf)}', end='', flush=True)
                elif ch == b'\x03': # Ctrl+C
                    raise KeyboardInterrupt
                else:
                    buf += ch
                    print('*', end='', flush=True)
            return buf.decode(encoding='utf-8')
    except ImportError:
        from getpass import getpass
    

    Please feel free to suggest any other changes, or ways to improve this; I hacked the changes together pretty quickly, especially with the Backspace logic.

    0 讨论(0)
  • 2020-11-28 14:07

    If you want a solution that works on Windows/macOS/Linux and on Python 2 & 3, you can install the stdiomask module:

    pip install stdiomask
    

    Unlike getpass.getpass() (which is in the Python Standard Library), the stdiomask module can display *** mask characters as you type.

    Example usage:

    >>> 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'
    

    Unfortunately this module, like Python's built-in getpass module, doesn't work in IDLE or Jupyter Notebook.

    More details at https://pypi.org/project/stdiomask/

    0 讨论(0)
  • 2020-11-28 14:14

    I have combined the answers of @Tigran Aivazian and @Ahndwoo into fully working solution:

    • ! additional code for the backspace {b'\x08', b'\x7f'}: # Backspace is added
    • for the Ctrl+C combination the silent return is used. The raise KeyboardInterrupt is commented now, but can be uncommented for raise the error.
    # if getch module is available, then we implement our own getpass() with asterisks,
    # otherwise we just use the plain boring getpass.getpass()
    try:
        from getch import getch
        def getpass(prompt):
            """Replacement for getpass.getpass() which prints asterisks for each character typed"""
            print(prompt, end='', flush=True)
            buf = b''
            while True:
                ch = getch().encode()
                if ch in {b'\n', b'\r', b'\r\n'}:
                    print('')
                    break
                elif ch == b'\x03': # Ctrl+C
                    # raise KeyboardInterrupt
                    return ''
                elif ch in {b'\x08', b'\x7f'}: # Backspace
                    buf = buf[:-1]
                    print(f'\r{(len(prompt)+len(buf)+1)*" "}\r{prompt}{"*" * len(buf)}', end='', flush=True)
                else:
                    buf += ch
                    print('*', end='', flush=True)
    
            return buf.decode(encoding='utf-8')
    except ImportError:
        from getpass import getpass
    
    password = getpass('Enter password: ')
    print(password)
    
    0 讨论(0)
提交回复
热议问题