whoopscheckmate
whoopscheckmate

Reputation: 876

Python get user input password with timeout

I'm writing a Python application and would like to prompt a user for their password. If they do not enter it within 60 seconds, the program should exit. If they do enter it, their password should be hidden in the terminal.

How do I do this?

Context

I've seen posts like this one that suggest methods to input some user input with a timeout. However, these solutions don't hide input like getpass does. I'm wondering if there's some functionality that could use getpass or something like it.

Upvotes: 1

Views: 754

Answers (2)

nassoo
nassoo

Reputation: 59

It's not a perfect solution, but you could try using multiprocessing:

import multiprocessing
import queue


def take_input(q):
    stdin = open(0)
    print("Enter your input: (y/n) >> ", end="", flush=True)
    user_input = stdin.readline()
    q.put(user_input)


def confirm_user_input():
    value = ''
    if __name__ == "__main__":
        q = multiprocessing.Queue()
        process = multiprocessing.Process(target=take_input, args=(q,))
        process.start()
        try:
            value = q.get(timeout=10)
        except queue.Empty:
            print("no input...")
        process.terminate()
        process.join()

        if value.strip() == 'y':
            print("confirmed: do something in this case...")
        else:
            print("not confirmed: do something else in that case...")


confirm_user_input()

This doesn't use input(), but it waits for response for n seconds and if there's no input, continues with something else and it doesn't require Unix system. Keep in mind it needs to be in main. Otherwise you should call it from the main with something like this:

if __name__ == '__main__':
     freeze_support()
     confirm_user_input()

In that case remove if __name__ == "__main__": from the function. May be you could implement it in your code.

Upvotes: 1

Lucas
Lucas

Reputation: 382

Inspired by this (which only seems to only work on Unix systems), you can timeout a function call by signal.alarm()

import getpass
import signal


def timeout(signum, frame):
    print('Timeout!')
    exit()


def get_user_password():
    upass = getpass.getpass()
    return upass


if __name__ == "__main__":
    signal.signal(signal.SIGALRM, timeout)
    timeout_in_s = 10

    signal.alarm(timeout_in_s)
    upass = get_user_password()
    signal.alarm(0)  # Stop alarm

Upvotes: 1

Related Questions