简体   繁体   中英

Break out of a while loop while stuck on user input

I have the following code to get user input to do certain tasks. What I want is to break out of the user prompt when some other task, outside this module, is completed. So even though the shell is showing 'Enter Command:', I want it to stop waiting for a prompt from the user and continue to the other task. Is this even possible and if so, how? Thanks in advance.

    def get_user_input():
        while True:
            info = str(raw_input('Enter Command:'))
            if info == 'exit':
                break
            if info == 'do_something':
                do_something()

Edit: Actually this is already in a thread and the thread closes correctly. The issue is the screen is stuck on the user prompt even though the user prompt is useless at that point since the thread calling for the input is already closed. Any suggestions?

Using Signals

you can use signal module (linux / unix only)

import signal


class UserInputTimeoutError(Exception):
    pass


def handler(signum, frame):
    raise UserInputTimeoutError('no input from user')

# Set the signal handler and a 5-second alarm
signal.signal(signal.SIGALRM, handler)
signal.alarm(5)

try:
    # This may hang indefinitely
    user_input = raw_input('please insert something here:')
    print('got %s from user' % user_input)

    # cancel the alarm signal
    signal.alarm(0)
except UserInputTimeoutError:
    print('\nno input from user')

output when input is 'hello':

please insert something here:hello
got hello from user

output when no input for 5 seconds:

please insert something here:
no input from user


Using Select

another option is to use select.select() for non-blocking io operation.

the get_user_input function tries to read every 0.1 sec the sys.stdin, if there is data to read it reads single byte. if it encounters a new line it returns the string.

if the timeout passed we exit returning None

the code:

import select
import sys
import time


def get_user_input(msg, timeout=5):
    print(msg)
    user_input = []
    stime = time.time()

    while time.time() - stime <= timeout:
        readables, _, _ = select.select([sys.stdin], [], [], 0.1)
        if not readables:
            continue
        chr = readables[0].read(1)
        if chr == '\n':
            return ''.join(user_input)
        user_input.append(chr)

user_input = get_user_input('please insert something:')

if user_input is None:
    print('no user input')
else:
    print('input is %s' % user_input)

example output for input hello select :

please insert something:
hello select
input is hello select

example when no input for 5 seconds:

please insert something:
no user input

Windows support

if you use windows for some reason you can check out this answer about msvcrt module.

basically its the same as select.select for non-blocking io using msvcrt.kbhit() to check if user returned input.

if you need more info please update about your OS.

I think you can use this answer to read until a timeout, then check a variable and exit if the variable is set to false. If not then attempt to read again.

https://stackoverflow.com/a/2904057/2066459

import sys, select

print "Answer me!"
while var:
    i, o, e = select.select( [sys.stdin], [], [], 10 )

    if (i):
      print "You said", sys.stdin.readline().strip()
      break

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM