Skip to content

Instantly share code, notes, and snippets.

@grubberr
Last active June 13, 2016 11:19
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save grubberr/5501e1a9760c3eab5e0a to your computer and use it in GitHub Desktop.
Save grubberr/5501e1a9760c3eab5e0a to your computer and use it in GitHub Desktop.
Non-blocking line iterator can return 'None' if stream does not produce data after timeout period
#!/usr/bin/python
import os
import sys
import select
class AsyncLineReader(object):
BUFSIZE = 4096
def __init__(self, stream, timeout=5):
self.stream = stream
self.timeout = timeout
self.lines = []
self.current_fragments = []
self.poll = select.poll()
self.poll.register(
self.stream.fileno(),
select.POLLIN|select.POLLPRI)
def read_or_timeout(self):
if self.poll.poll(self.timeout*1000):
return os.read(self.stream.fileno(), self.BUFSIZE)
return None
def process(self):
buff = self.read_or_timeout()
if buff:
while True:
pos = buff.find(b'\n')
if pos == -1:
self.current_fragments.append(buff)
break
self.current_fragments.append(buff[:pos+1])
buff = buff[pos+1:]
self.lines.append(b''.join(self.current_fragments))
self.current_fragments = []
elif buff == '':
raise StopIteration
def __iter__(self):
return self
def __next__(self):
if not self.lines:
self.process()
if self.lines:
return self.lines.pop(0)
return None
next = __next__
for msg in AsyncLineReader(sys.stdin, timeout=5):
if msg:
print("LINE: ", repr(msg))
else:
print("TIMEOUT...")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment