mirror of
https://github.com/YunoHost/moulinette.git
synced 2024-09-03 20:06:31 +02:00
[ref] Use a new asynchronous file reader helper
This commit is contained in:
parent
4cf898d9c7
commit
2be9da941f
1 changed files with 33 additions and 47 deletions
|
@ -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
|
|
||||||
|
|
Loading…
Reference in a new issue