Playing around with non-blocking console input, using Python's selectors
in combination with sys.stdin
, there is something I do not understand:
Suppose I want to exit a loop when a user presses Enter, possibly after entering some other characters first.
If I do a blocking read, as follows, the process always finishes after the first linefeed \n
it encounters, as expected, regardless of any preceding characters:
import sys
character = ''
while character != '\n':
character = sys.stdin.read(1)
Now consider the following minimized example of a non-blocking read:
import sys
import selectors
selector = selectors.DefaultSelector()
selector.register(fileobj=sys.stdin, events=selectors.EVENT_READ)
character = ''
while character != '\n':
for key, __ in selector.select(timeout=0):
character = key.fileobj.read(1)
If I hit Enter as the first input, that generates a linefeed character, and the process finishes, as expected.
However, if I input some other characters first, followed by Enter, the process does not finish: I need to hit Enter again before it does.
Apparently this implementation only works if the linefeed is the first input.
There's probably a good reason for this, but I do not see it at the moment, and could not find any related questions.
Does this have to do with my non-blocking implementation, or is it a stdin
buffer thing, or perhaps something to do with the console or terminal implementation?
(I am running this from a python 3.8 shell on ubuntu.)