[ref] Use a new asynchronous file reader helper

This commit is contained in:
Jérôme Lebleu 2015-11-14 21:59:38 +01:00
parent 4cf898d9c7
commit 2be9da941f

View file

@ -1,59 +1,45 @@
from threading import Thread import threading
from Queue import Queue, Empty import Queue
# Read from a stream --------------------------------------------------- # Read from a stream ---------------------------------------------------
class NonBlockingStreamReader: class AsynchronousFileReader(threading.Thread):
"""A non-blocking stream reader """
Helper class to implement asynchronous reading of a file
in a separate thread. Pushes read lines on a queue to
be consumed in another thread.
Open a separate thread which reads lines from the stream whenever data Based on:
becomes available and stores the data in a queue. http://stefaanlippens.net/python-asynchronous-subprocess-pipe-reading
Based on: http://eyalarubas.com/python-subproc-nonblock.html
Keyword arguments:
- stream -- The stream to read from
""" """
def __init__(self, stream): def __init__(self, fd, queue):
self._s = stream assert isinstance(queue, Queue.Queue)
self._q = Queue() assert callable(fd.readline)
threading.Thread.__init__(self)
self._fd = fd
self._queue = queue
def _populateQueue(stream, queue): def run(self):
"""Collect lines from the stream and put them in the queue""" """The body of the tread: read lines and put them on the queue."""
while True: for line in iter(self._fd.readline, ''):
line = stream.readline() self._queue.put(line)
if line:
queue.put(line)
else:
break
self._t = Thread(target=_populateQueue, args=(self._s, self._q)) def eof(self):
self._t.daemon = True """Check whether there is no more content to expect."""
# Start collecting lines from the stream return not self.is_alive() and self._queue.empty()
self._t.start()
def readline(self, block=False, timeout=None): def join(self, timeout=None, close=True):
"""Read line from the stream """Close the file and join the thread."""
if close:
self._fd.close()
threading.Thread.join(self, timeout)
Attempt to pull from the queue the data and return it. If no data is
available or timeout has expired, it returns None.
Keyword arguments: def start_async_file_reading(fd):
- block -- If True, block if necessary until data is available """Helper which instantiate and run an AsynchronousFileReader."""
- timeout -- The number of seconds to block queue = Queue.Queue()
reader = AsynchronousFileReader(fd, queue)
""" reader.start()
try: return (reader, queue)
return self._q.get(block=timeout is not None,
timeout=timeout)
except Empty:
return None
def close(self):
"""Close the stream"""
try:
self._s.close()
except IOError:
pass