executifs executifs - 30 days ago 8
Python Question

Weird select.select() behavior in Python

I'm trying to read from stdin character by character with a Python script, using

to be notified whenever something is available. I'm facing a behavior that I don't understand; it's probably best illustrated with an example. First of all, here is a sample select code:

import select
import sys

while True:
r, w, e = select.select([sys.stdin], [], [])
print "Read: %s" % sys.stdin.read(1)

Now here is a sample run of the script:

/tmp$ python test.py
AAAA # I type in a few chars then ENTER.
Read: A # Only one char is detected :(
BBBB # I type in more characters
Read: A # Now all the previous characters are detected!?
Read: A
Read: A
Read: # ('\n' is read which I want)

Read: B # Wait, where are the other Bs?
CCCC # I need to type more chars so that BBB is printed, and the first C.

As you can see above, if multiple characters are typed in
, only the first one is printed. Then, if more characters are added, all the remaining ones from the previous input are printed plus the first one of the new input.

What am I doing wrong?

Answer Source

select.select is unaware of the buffering in a Python file object (such as sys.stdin). You can bypass the file object entirely, though this will interact strangely with attempts to read from sys.stdin:

import select
import os
import sys

while True:
    r, w, e = select.select([sys.stdin], [], [])
    print os.read(sys.stdin.fileno(), 1)