问题
执行这两个函数时与STDIN冲突。什么会导致第二个函数无法正确读取STDIN?如果未执行第一个功能,则第二个功能在读取输入时没有问题。
清除STDIN缓冲区我试过了:
'sys.stdin.flush'
'tcflush(sys.stdin, TCIOFLUSH)'
Python代码
import sys, select
def stdin_read():
print "[stdin read] You must answer Y/N and press ENTER"
sys.stdout.flush()
response = sys.stdin.read(1)
print "You said '{}'".format(response)
def stdin_timeout():
print "[stdin timeout] You must answer YES / NO in 10 seconds and press ENTER"
sys.stdout.flush()
sys.stdin.flush()
i, o, e = select.select( [sys.stdin], [], [], 10 )
if (i):
print "You said '{}'".format(sys.stdin.readline().strip())
exit(0)
else:
print "You said nothing!"
exit(1)
stdin_read()
stdin_timeout()
Python输出两种功能:
:~# python input.py
[stdin read] You must answer Y/N and press ENTER
n
You said 'n'
[stdin timeout] You must answer YES / NO in 10 seconds and press ENTER
no
You said ''
:~# no
-bash: no: command not found
Python输出第二功能
~# python input.py
[stdin timeout] You must answer YES / NO in 10 seconds and press ENTER
no
You said 'no'
答案 0 :(得分:1)
问题来自the behaviour of stdin flushing in unix
我会通过提交您的代码来回答:
import sys, select
def stdin_read():
print "[stdin read] You must answer Y/N and press ENTER"
# sys.stdout.flush() # not needed
# you are reading one byte here, but the user enters at least two bytes
# (e.g 'y' + LF(enter key)) so the LF byte (and possibly additional bytes)
# remain in the stdin buffer.
response = sys.stdin.read(1) # (->LF REMAINS)
print "You said '{}'".format(response)
def stdin_timeout():
print "[stdin timeout] You must answer YES / NO in 10 seconds and press ENTER"
#sys.stdout.flush() # not needed
# the behaviour of stdin flushing in unix is not defined (see
# link above)
sys.stdin.flush()
# thus the LF still remains in the stdin buffer
# the select call blocks until the file discriptor is 'ready' for
# the corresponding i/o operation. DISCLAIMER: assumptions are
# following.... By default python does a open call which uses
# buffered reads, so even if you did a read(1) it will likely read
# more data from stdin and the select call blocks until the next LF
# arrives.
i, o, e = select.select( [sys.stdin], [], [], 10 )
if (i):
# you are just reading the left over bytes from above (->LF REMAINS)
print "You said '{}'".format(sys.stdin.readline().strip())
# Proof: readline() again:
print "You missed '{}'".format(sys.stdin.readline().strip())
exit(0)
else:
print "You said nothing!"
exit(1)
stdin_read()
stdin_timeout()
但也许最好使用另一种方法Keyboard input with timeout in Python