From 0636a032beaa971a84556600a94d3936306323f5 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Wed, 18 Sep 2019 21:51:39 -0700 Subject: [PATCH] Added threading functions --- scripts/wk/exe.py | 45 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 44 insertions(+), 1 deletion(-) diff --git a/scripts/wk/exe.py b/scripts/wk/exe.py index a3a29477..6dfd978e 100644 --- a/scripts/wk/exe.py +++ b/scripts/wk/exe.py @@ -1,10 +1,13 @@ -"""WizardKit: Executable functions""" +"""WizardKit: Execution functions""" #vim: sts=2 sw=2 ts=2 import logging import re import subprocess +from threading import Thread +from queue import Queue, Empty + import psutil @@ -12,6 +15,38 @@ import psutil LOG = logging.getLogger(__name__) +# Classes +class NonBlockingStreamReader(): + """Class to allow non-blocking reads from a stream.""" + # pylint: disable=too-few-public-methods + # Credits: + ## https://gist.github.com/EyalAr/7915597 + ## https://stackoverflow.com/a/4896288 + + def __init__(self, stream): + self.stream = stream + self.queue = Queue() + + def populate_queue(stream, queue): + """Collect lines from stream and put them in queue.""" + while True: + line = stream.read(1) + if line: + queue.put(line) + + self.thread = start_thread( + populate_queue, + args=(self.stream, self.queue), + ) + + def read(self, timeout=None): + """Read from queue if possible, returns item from queue.""" + try: + return self.queue.get(block=timeout is not None, timeout=timeout) + except Empty: + return None + + # Functions def build_cmd_kwargs(cmd, minimized=False, pipe=True, shell=False, **kwargs): """Build kwargs for use by subprocess functions, returns dict. @@ -132,6 +167,14 @@ def run_program(cmd, check=True, pipe=True, shell=False, **kwargs): return subprocess.run(**cmd_kwargs) +def start_thread(function, args=None, daemon=True): + """Run function as thread in background, returns Thread object.""" + args = args if args else [] + thread = Thread(target=function, args=args, daemon=daemon) + thread.start() + return thread + + def wait_for_procs(name, exact=True, timeout=None): """Wait for all process matching name.""" LOG.debug('name: %s, exact: %s, timeout: %s', name, exact, timeout)