-1

I have seen other posts, and searched for a while and read documentation. But I cannot seem to understand the answers. Closest I got was the signal module, but the documentation confused me honestly. I need to break from a loop, without using raw_input, the Ctrl-C is perfect, except I need to change it to activate if the user clicks SPACE or ENTER.

from time import sleep
try:
while True:
    print "I'm looping!"
    sleep(1)
except KeyboardInterrupt:   
print "The loop has ended!"

This loop would be perfect If i could just change the keys for the KeyboardInterrupt error.

Hayden
  • 147
  • 1
  • 1
  • 10
  • This looks helpful for your problem: https://stackoverflow.com/questions/13207678/whats-the-simplest-way-of-detecting-keyboard-input-in-python-from-the-terminal?utm_medium=organic&utm_source=google_rich_qa&utm_campaign=google_rich_qa – Xantium May 22 '18 at 07:54
  • 1
    Possible duplicate of [How to kill a while loop with a keystroke?](https://stackoverflow.com/questions/13180941/how-to-kill-a-while-loop-with-a-keystroke) – Ofer Sadan May 22 '18 at 07:54
  • I saw that post as well Simon, sadly it confused me a bit. – Hayden May 22 '18 at 07:59

1 Answers1

1

This is an interesting and surprisingly complicated problem (not sure why the downvotes...) You have to bypass the standard "read till the end of line" as well as add a timeout on normally blocking read. Here is my answer (which works only on linux/mac but see the links on ideas of extending it to Windows):

import select
import sys, termios


def getchar():
    char = '_'
    fd = sys.stdin.fileno()
    old = termios.tcgetattr(fd)
    new = termios.tcgetattr(fd)
    new[3] = new[3] & ~(termios.ECHO | termios.ICANON) # turn off echo and canonical mode which sends data on delimiters (new line or OEF, etc)
    try:
        termios.tcsetattr(fd, termios.TCSADRAIN, new) # terminal is now 
        ready, steady, go = select.select([sys.stdin], [], [], 1)
        if ready:
            char = sys.stdin.read(1)
    finally:
        termios.tcsetattr(fd, termios.TCSADRAIN, old)
    return char


try:
    while True:
        print "I'm looping!"
        c = getchar()
        if c in ' \n':
            print "The loop has ended!"
            break
except KeyboardInterrupt:
    print "The loop has ended!"

It is a combination of this answer and this answer. Apparently there is also readchar library as suggested by this answer.

Roman Kutlak
  • 2,684
  • 1
  • 19
  • 24