3

How do I read everything there is from the stdin buffer in python without blocking? None of the stack overflow solutions I found work as my stdin is non-interactive.

I tried:

tcflush

tcflush(sys.stdin, TCIOFLUSH) which does not work on non-interactive stdin.

select

while select.select([sys.stdin], [], [], 0) == ([sys.stdin], [], []):
  sys.stdin.read(1)

and

while len(select.select([sys.stdin.fileno()], [], [], 0.0)[0])>0:
  os.read(sys.stdin.fileno(), 4096)

Which do not work because the condition in the while head is always False.

Any other ideas?

Edit

To be more precise:

My code should

  • do nothing if the input buffer is empty
  • empty the buffer if there is something in it

So it should never block.

3
  • 1
    What do you mean by 'do not work'? If select says there is nothing to be read, how to you know that there is something to be read? Commented Mar 6, 2015 at 20:05
  • @TerryJanReedy because if I put a input() after the while statement, it does not block. The input() also does not block if put before the while statement so I am pretty sure there is something in the buffer. Commented Mar 6, 2015 at 22:48
  • Are you trying this in Windows? The select functionality in Windows is provided by WinSock, and thus only works on sockets. See the documentation. Commented Mar 6, 2015 at 23:02

2 Answers 2

1

You are using a zero seconds timeout in your select() call, which effectively makes select into a one-shot poll operation that does not wait until data is available.

while len(select.select([sys.stdin.fileno()], [], [], 0.0)[0])>0:
                                                       ^
                                                       |
                                                This means don't wait

Try instead:

while len(select.select([sys.stdin.fileno()], [], [], None)[0]) > 0:
Sign up to request clarification or add additional context in comments.

2 Comments

Not blocking is the whole point ;-) See the clarification I just added.
But then that's because there isn't any data to read. What is stdin connected to?
0

Thanks for your suggestions so far. Apparently this was, after all, one of those strange concurrency problems.

When I set a timeout in the select call, it works. So it seems that the buffer really has not been filled at the moment I call the select.

Does not work (same as in the question):

while select.select([sys.stdin], [], [], 0) == ([sys.stdin], [], []):
  sys.stdin.read(1)

Does work:

while select.select([sys.stdin], [], [], 0.01) == ([sys.stdin], [], []):
  sys.stdin.read(1)

As the things I want to read are line-based, I can read a whole line at a time with input instead of reading single characters with read though, and then the slowdown of the timeout in the while loop will not be noticeable. (There will be max. 5-10 lines in the buffer).

I am not totally satisfied with this solution as it involves waiting for an arbitrary amount of time (will 0.01 always be enough?). But on the other hand I can't think of a better solution right now as I can't influence the code writing to "my stdin".

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.