Reputation: 23854
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.
Upvotes: 24
Views: 66168
Reputation: 31
There is a Console API function for this task, FlushConsoleInputBuffer. A cross-platform solution would look like this:
import os
if os.name == "posix":
import sys
import termios
else:
import ctypes
from ctypes import wintypes
# Dynamic link libraries aliases
kernel32 = ctypes.windll.kernel32
# Standard console devices
STD_INPUT_HANDLE = -10
INVALID_HANDLE_VALUE = wintypes.HANDLE(-1).value
kernel32.GetStdHandle.argtypes = (wintypes.DWORD, )
kernel32.GetStdHandle.restype = wintypes.HANDLE
def get_std_handle(nStdHandle: int) -> wintypes.HANDLE | None:
'''
Function GetStdHandle from ProcessEnv.h
'''
result = kernel32.GetStdHandle(nStdHandle)
if result == INVALID_HANDLE_VALUE or result is None:
return None
return result
kernel32.FlushConsoleInputBuffer.argtypes = (wintypes.HANDLE, )
kernel32.FlushConsoleInputBuffer.restype = wintypes.BOOL
def flush_console_input_buffer(hConsoleInput: wintypes.HANDLE) -> int:
'''
Function FlushConsoleInputBuffer from ConsoleApi2.h
'''
return kernel32.FlushConsoleInputBuffer(hConsoleInput)
def discard_input() -> bool:
'''
Discard all input events.
Returns:
bool: Execution result.
'''
if os.name == "posix":
termios.tcflush(sys.stdin.fileno(), termios.TCIOFLUSH)
return True
if (hConsoleInput := get_std_handle(STD_INPUT_HANDLE)) is None:
return False
if flush_console_input_buffer(hConsoleInput):
return True
return False
discard_input()
FlushConsoleInputBuffer is available since Windows 2000. The code above uses the walrus operator (PEP 572, 3.8) and union type hint (PEP 604, 3.10).
Add this import to use on Python 3.8+:
from __future__ import annotations
Upvotes: 0
Reputation: 31
I have used (and worked in my case):
import sys
...
sys.stdin.flush()
...
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.
Upvotes: 1
Reputation: 9334
#!/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
Upvotes: 6
Reputation: 385
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.
Upvotes: 20
Reputation: 2808
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
Upvotes: 14
Reputation: 1310
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
Upvotes: 10