I have a program that constantly pipes status information to a python script through stdin. Those are separated by a new line, so one update is one new line in stdin.
In my Python script I have an endless loop that waits for new input from stdin and then does some post processing. I want this post-processing to happen as soon as new information is available from stdin but at the least after 5 seconds.
Currently I have:
line = ""
while True:
if sys.stdin in select([sys.stdin], [], [], 5)[0]:
line = sys.stdin.readline().strip()
do_something(line) # do this only if something can be read from stdin
# do this in any case every 5 secs
# (but does rely on the most recent info from stdin)
do_more(line)
This works great if one loop iteration finishes before a new update is available from stdin.
However, if a new line is written to stdin while the script is processing the previous update select
blocks for 5 seconds instead of returning immediately. Additionally, in case of an update between loop iterations select
without a timeout returns false:
sys.stdin in select([sys.stdin], [], [], 0)[0]
I tried to change the condition this way:
if not sys.stdin.isatty() or sys.stdin in select([sys.stdin], [], [], 5)[0]:
This works for detecting changes between loop iterations but sys.stdin.isatty()
blocks if no new line is available, so select
is never evaluated.
What I actually need is a function that tests if the stdin buffer is empty or not in a non-blocking way. Is there such a function? Or any other way to achieve what I want? I'm only interested in Linux so portability is not an issue.