22

I'm writing a simple alarm utility in Python.

#!/usr/bin/python

import time
import subprocess
import sys

alarm1 = int(raw_input("How many minutes (alarm1)? "))

while (1):
    time.sleep(60*alarm1)
    print "Alarm1"
    sys.stdout.flush()
    doit = raw_input("Continue (Y/N)?[Y]: ")
    print "Input",doit
    if doit == 'N' or doit=='n':
        print "Exiting....."
        break

I want to flush or discard all the key strokes that were entered while the script was sleeping and only accept the key strokes after the raw_input() is executed.

I'm running this on Windows XP.

Zoe
  • 27,060
  • 21
  • 118
  • 148
Amjith
  • 22,626
  • 14
  • 43
  • 38

5 Answers5

16

From Rosetta Code

def flush_input():
    try:
        import msvcrt
        while msvcrt.kbhit():
            msvcrt.getch()
    except ImportError:
        import sys, termios    #for linux/unix
        termios.tcflush(sys.stdin, termios.TCIOFLUSH)

The try part is for Windows platform. I have not personally tested this part. But the except section works on linux terminal. termios module has some terminal interface functions. the tcflush can flush input or output buffered data. This part definitely works in my tests.

hyper-neutrino
  • 5,272
  • 2
  • 29
  • 50
kollery
  • 335
  • 4
  • 9
  • 1
    Why should the OP trust your answer? A **good answer** will always have an explanation of what was done and why it was done in such a manner, not only for the OP but for future visitors to SO. – B001ᛦ Aug 17 '16 at 10:08
  • 2
    @bub, thanks for the hint. I didn't think there is much explantation needed on this one. will edit my answer – kollery Aug 17 '16 at 10:19
  • This is similar to what @Callahad had. Just wraps in a nice 'def' – kollery Aug 17 '16 at 10:25
  • termios.tcflush(sys.stdin, termios.TCIOFLUSH) good idea – Peter Moore Mar 01 '23 at 16:32
14

It would help to know what operating system you're using, as this is a very operating-system-specific question. For example, Kylar's answer doesn't work on Windows because sys.stdin doesn't have a fileno attribute.

I was curious and threw together a solution using curses, but this won't work on Windows either:

#!/usr/bin/python                                                               

import time
import sys
import curses

def alarmloop(stdscr):
    stdscr.addstr("How many seconds (alarm1)? ")
    curses.echo()
    alarm1 = int(stdscr.getstr())
    while (1):
        time.sleep(alarm1)
        curses.flushinp()
        stdscr.clear()
        stdscr.addstr("Alarm1\n")
        stdscr.addstr("Continue (Y/N)?[Y]:")
        doit = stdscr.getch()
        stdscr.addstr("\n")
        stdscr.addstr("Input "+chr(doit)+"\n")
        stdscr.refresh()
        if doit == ord('N') or doit == ord('n'):
            stdscr.addstr("Exiting.....\n")
            break

curses.wrapper(alarmloop)

EDIT: ah, Windows. Then you can use the msvcrt module. Note that the code below isn't perfect, and it doesn't work in IDLE at all:

#!/usr/bin/python

import time
import subprocess
import sys
import msvcrt

alarm1 = int(raw_input("How many seconds (alarm1)? "))

while (1):
    time.sleep(alarm1)
    print "Alarm1"
    sys.stdout.flush()

    # Try to flush the buffer
    while msvcrt.kbhit():
        msvcrt.getch()

    print "Continue (Y/N)?[Y]"
    doit = msvcrt.getch()
    print "Input",doit
    if doit == 'N' or doit=='n':
        print "Exiting....."
        break
Peter Milley
  • 2,768
  • 19
  • 18
10

On Unices, you can use termios.tcflush():

import time
import subprocess
import sys
from termios import tcflush, TCIOFLUSH

alarm1 = int(raw_input("How many minutes (alarm1)? "))

while (1):
    time.sleep(60*alarm1)
    print "Alarm1"
    sys.stdout.flush();
    tcflush(sys.stdin, TCIOFLUSH)
    doit = raw_input("Continue (Y/N)?[Y]: ")
    print "Input",doit
    if doit == 'N' or doit=='n':
        print "Exiting....."
        break
Callahad
  • 1,280
  • 6
  • 9
5
#!/usr/bin/python

import time
import subprocess
import sys
import os, select

alarm1 = int(raw_input("How many minutes (alarm1)? "))

while (1):
    time.sleep(3*alarm1)
    print "Alarm1"
    sys.stdout.flush()
    while select.select([sys.stdin.fileno()], [], [], 0.0)[0]:
        os.read(sys.stdin.fileno(), 4096)
    doit = raw_input("Continue (Y/N)?[Y]: ")
    print "Input",doit
    if doit == 'N' or doit=='n':
        print "Exiting....."
        break
ShadowRanger
  • 143,180
  • 12
  • 188
  • 271
Kylar
  • 8,876
  • 8
  • 41
  • 75
  • I reduced your sleep time to 3 seconds, for testing :) – Kylar Mar 26 '10 at 03:47
  • This code didn't work on Windows XP. Can you please explain the various parameters you are sending to the select.select()? – Amjith Mar 26 '10 at 05:22
  • 3
    Ahh, I didn't realize you were on windows. This won't work at all (I saw the /usr/bin/python and assumed. My bad.) The docs for select are here: http://docs.python.org/library/select.html but on windows it will only bind to a socket. – Kylar Mar 26 '10 at 17:35
0

Solution:

I have used (and worked in my case):

import sys

...
sys.stdin.flush()
...

Why this answer?

I have added this answer to this thread because I got here with the question "What was the syntax for flushing stdin?". I read the entries and thought that there had to be some flush method for stdin. I found it. I was surprised that it was not used in any entry and I thought that it should be.

Related documentation

  • Hello, please don't just submit code in your answer(s), add some details as to why you think this is the optimal solution. – Destroy666 May 29 '23 at 17:47
  • Thank you for your comment. I really thought that my simple answer was very appropriate for people with the same question of this thread ("How to flush the input stream?"). I actually came to this thread with the same question, read the entries, and thought that there had to be some flush method for stdin. I found it and was surprised that it was not used in any entry. – Carlos García-Martínez May 31 '23 at 08:31
  • Ok. I meant more like "it's better than other solutions because X, Y, Z", you could also link to the documentation or anything alike. – Destroy666 May 31 '23 at 14:24
  • Thank you for your suggestion. It is certainly a good idea to refer to the relevant documentation. I will try to take this into account in future entries. On the other hand, I don't think this solution is better than the others, but complementary. The others address an aspect commented in the text of the question, while mine simplifies the action of flushing stdin (title of the question). – Carlos García-Martínez Jun 05 '23 at 14:29