如何清空输入流?

22

我正在用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上运行此脚本。


2
sys.stdout.flush(); 后面不需要加分号。 - Vlad the Impala
我错了,你是对的,我不需要分号。已修复代码。 - Amjith
2
“清除或丢弃所有按键?”你的意思是“读取并忽略”吗?你不能轻易地“清除”输入。为什么不做简单、明显的事情:读取它们并忽略它们呢? - S.Lott
5个回答

16

来自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可以刷新输入或输出缓冲数据。根据我的测试,这部分肯定有效。


1
为什么楼主应该相信你的回答?一个好的回答总是会解释做了什么以及为什么以这种方式完成,不仅为了楼主,也为了未来访问 Stack Overflow 的用户。 - B001ᛦ
2
@bub,感谢你的提示。我觉得这个问题不需要太多解释。我会编辑我的答案。 - kollery
这与@Callahad所拥有的类似,只是用一个漂亮的“def”包装起来。 - kollery
termios.tcflush(sys.stdin, termios.TCIOFLUSH) 是个好主意。 - Peter Moore

14

知道你使用的操作系统是什么将有所帮助,因为这是一个非常特定于操作系统的问题。例如,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\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)

编辑:啊,是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

我正在Windows xp上运行这个程序。 - Amjith
1
那么您可能想尝试使用msvcrt模块;请参见上面的编辑。 - Peter Milley

10

在Unix系统上,您可以使用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

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

我把你的睡眠时间缩短到3秒,只是为了测试 :) - Kylar
这段代码在Windows XP上无法运行。您能否解释一下您发送到select.select()的各个参数? - Amjith
4
啊,我没意识到你在使用Windows。这根本行不通(我看到了/usr/bin/python就假设了,我的错)。这里是select的文档:http://docs.python.org/library/select.html 但在Windows上它只能绑定到一个套接字。 - Kylar

0

解决方案:

我使用了(并在我的情况下起作用的):

import sys

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

为什么选择这个答案?
我将这个答案添加到这个帖子中,是因为我通过问题“清空stdin的语法是什么?”来到这里。我阅读了帖子并认为应该有一种清空stdin的方法。我找到了它。我很惊讶地发现它在任何帖子中都没有被使用,所以我觉得应该加上。
相关文档
- sys: [链接1](https://docs.python.org/3.12/library/sys.html) - io: [链接2](https://docs.python.org/3/library/io.html)

大家好,请不要只在您的回答中提交代码,还需要添加一些详细信息,解释为什么您认为这是最佳解决方案。 - Destroy666
感谢您的评论。我真的认为我的简单回答非常适合拥有相同问题的这个主题的人们(“如何刷新输入流?”)。实际上,我也带着同样的问题来到这个主题,阅读了条目,并认为必须有某种刷新stdin的方法。我找到了它并惊讶地发现它没有在任何条目中使用。 - Carlos García-Martínez
好的。我的意思是,“它比其他解决方案更好,因为X、Y、Z”,你还可以链接到文档或类似的内容。 - Destroy666
谢谢你的建议。参考相关文档确实是个好主意。我会尽量在以后的记录中考虑这一点。另一方面,我不认为这个解决方案比其他解决方案更好,而是互补的。其他解决方案涉及到问题文本中提到的一个方面,而我的解决方案简化了清空stdin的操作(问题的标题)。 - Carlos García-Martínez
谢谢你的建议。参考相关文档确实是个好主意。我会尽量在以后的记录中考虑这一点。另一方面,我不认为这个解决方案比其他解决方案更好,而是互补的。其他解决方案涉及到问题文本中提到的一个方面,而我的解决方案简化了清空标准输入的操作(问题的标题)。 - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接