Python STDIN User Input Issue

我的未来我决定 提交于 2019-12-11 14:27:02

问题


Issue

Conflict with STDIN when executing these two functions. What would cause the second function to not read STDIN correctly? If the first function is not executed, the second function has no issue reading the input.

To clear STDIN buffer I've tried:

'sys.stdin.flush'

'tcflush(sys.stdin, TCIOFLUSH)'

Python Code

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 Output Both Functions:

:~# 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 Output Second Function

~# python input.py
[stdin timeout] You must answer YES / NO in 10 seconds and press ENTER
no
You said 'no'

回答1:


The problem arises from the behaviour of stdin flushing in unix

I'll answer by commmenting your code:

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()

But maybe it would be better to use another approach Keyboard input with timeout in Python



来源:https://stackoverflow.com/questions/35018268/python-stdin-user-input-issue

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!