6

So I've been doing a little bit of reading up on how to exit a while loop by the user pressing the enter key and I've come up with the following:

import sys, select, os

switch = 1
i = 1
while switch == 1:
    os.system('cls' if os.name == 'nt' else 'clear')
    print "I'm doing stuff. Press Enter to stop me!"
    print i
    while sys.stdin in select.select([sys.stdin], [], [], 0)[0]:
        line = raw_input()
        if not line:
            print "Finished! =]"
            switch = 0
        else:
            print "Finished! =]"
            switch = 0
    i = i+1

Is there a way to tidy this up? In particular the "if not line" and the following "else" look messy. Can they be combined into one? A better alternative to using "switch"?

Initially if I typed a bunch of characters and then hit enter it didn't stop the loop. I would have to press enter again. The if not and else components are intended to set it up such that it would exit on the first press of enter.

user3394391
  • 487
  • 6
  • 15
  • Why not get rid of the `if`, as it does the same either way? Also, `while True` and `break` is neater than a flag – jonrsharpe Mar 13 '14 at 21:30
  • Does this actually work on Windows? The docs say that select.select only supports sockets on Windows: http://docs.python.org/2/library/select.html – Weeble Mar 13 '14 at 21:35
  • @Weeble I think this should work for Windows? http://code.activestate.com/recipes/146066-exiting-a-loop-with-a-single-key-press/ I'm coding on Ubuntu, personally. – user3394391 Mar 13 '14 at 21:38

1 Answers1

12

This worked for me:

import sys, select, os

i = 0
while True:
    os.system('cls' if os.name == 'nt' else 'clear')
    print "I'm doing stuff. Press Enter to stop me!"
    print i
    if sys.stdin in select.select([sys.stdin], [], [], 0)[0]:
        line = raw_input()
        break
    i += 1

You only need to check for the stdin being input once (since the first input will terminate the loop). If the conditions line/not line have result for you, you can combine them to one if statement. Then, with only one while statement being used, you can now use break instead of setting a flag.

limasxgoesto0
  • 4,555
  • 8
  • 31
  • 38
  • Nailed it. Thank you! – user3394391 Mar 13 '14 at 21:34
  • Actually in hindsight, I realize you don't even need ```if line or not line```... it's always True. – limasxgoesto0 Mar 13 '14 at 21:38
  • 1
    You do need the raw_input() call though, because if the user inputs anything besides Enter and then presses Enter, it throws a NameError. – limasxgoesto0 Mar 13 '14 at 21:39
  • 1
    If I had enough rep I would upvote the hell out of your solution. I hope others can benefit from this! – user3394391 Mar 13 '14 at 21:42
  • 1
    This is an excellent answer. Here is (I believe) the original source, which has further information about non-blocking stdin: https://repolinux.wordpress.com/2012/10/09/non-blocking-read-from-stdin-in-python/ – Blairg23 Jan 06 '16 at 19:33