如何刷新输入流?
- 2025-02-14 09:50:00
- admin 原创
- 39
问题描述:
我正在用 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
我想刷新或丢弃脚本休眠时输入的所有按键,并且仅在执行 raw_input() 后接受按键。
我在 Windows XP 上运行它。
解决方案 1:
来自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)
try 部分是针对 Windows 平台的。我还没有亲自测试过这部分。但是 except 部分在 linux 终端上是可以的。termios 模块有一些终端接口函数。tcflush 可以刷新输入或输出缓冲数据。这部分在我的测试中绝对可以正常工作。
解决方案 2:
了解您使用的操作系统会有所帮助,因为这是一个非常特定于操作系统的问题。例如,Kylar 的答案在 Windows 上不起作用,因为 sys.stdin 没有 fileno 属性。
我很好奇,并使用 curses 提出了一个解决方案,但这在 Windows 上也不起作用:
#!/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
")
stdscr.addstr("Continue (Y/N)?[Y]:")
doit = stdscr.getch()
stdscr.addstr("
")
stdscr.addstr("Input "+chr(doit)+"
")
stdscr.refresh()
if doit == ord('N') or doit == ord('n'):
stdscr.addstr("Exiting.....
")
break
curses.wrapper(alarmloop)
编辑:啊,Windows。然后您可以使用 msvcrt 模块。请注意,下面的代码并不完美,而且在 IDLE 中根本不起作用:
#!/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
解决方案 3:
在 Unices 上,您可以使用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
解决方案 4:
#!/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
解决方案 5:
解决方案:
我曾经使用过(并且在我的案例中有效):
import sys
...
sys.stdin.flush()
...
为什么是这个答案?
我把这个答案添加到这个帖子中,因为我来这里时遇到了一个问题:“刷新 stdin 的语法是什么?”我读了这些条目,认为 stdin 一定有某种刷新方法。我找到了它。我很惊讶它没有在任何条目中使用,我认为它应该是。
相关文档
系统:https ://docs.python.org/3.12/library/sys.html
io:https ://docs.python.org/3/library/io.html
解决方案 6:
有一个用于此任务的控制台 API 函数,FlushConsoleInputBuffer。跨平台解决方案如下所示:
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 自 Windows 2000 起可用。上面的代码使用了海象运算符(PEP 572,3.8)和联合类型提示(PEP 604,3.10)。
添加此导入以在 Python 3.8+ 上使用:
from __future__ import annotations