model of DCN pyramidal neuron
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

112 lines
3.0 KiB

from __future__ import print_function
"""
Utility class for spawning and controlling CLI processes.
See: http://stackoverflow.com/questions/375427/non-blocking-read-on-a-subprocess-pipe-in-python
"""
import sys, time
from subprocess import PIPE, Popen
from threading import Thread
try:
from Queue import Queue, Empty
except ImportError:
from queue import Queue, Empty # python 3.x
ON_POSIX = "posix" in sys.builtin_module_names
class Process(object):
"""
Process encapsulates a subprocess with queued stderr/stdout pipes.
Wraps most methods from subprocess.Popen.
For non-blocking reads, use proc.stdout.get_nowait() or
proc.stdout.get(timeout=0.1).
"""
def __init__(self, exec_args, cwd=None):
self.proc = Popen(
exec_args,
stdout=PIPE,
stdin=PIPE,
stderr=PIPE,
bufsize=1,
close_fds=ON_POSIX,
universal_newlines=True,
cwd=cwd,
)
self.stdin = self.proc.stdin
# self.stdin = PipePrinter(self.proc.stdin)
self.stdout = PipeQueue(self.proc.stdout)
self.stderr = PipeQueue(self.proc.stderr)
for method in ["poll", "wait", "send_signal", "kill", "terminate"]:
setattr(self, method, getattr(self.proc, method))
class PipePrinter(object):
""" For debugging writes to a pipe.
"""
def __init__(self, pipe):
self._pipe = pipe
def __getattr__(self, attr):
return getattr(self._pipe, attr)
def write(self, strn):
print("WRITE:" + repr(strn))
return self._pipe.write(strn)
class PipeQueue(Queue):
"""
Queue that starts a second process to monitor a PIPE for new data.
This is needed to allow non-blocking pipe reads.
"""
def __init__(self, pipe):
Queue.__init__(self)
self.thread = Thread(target=self.enqueue_output, args=(pipe, self))
self.thread.daemon = True # thread dies with the program
self.thread.start()
@staticmethod
def enqueue_output(out, queue):
for line in iter(out.readline, b""):
queue.put(line)
# print "READ: " + repr(line)
out.close()
def read(self):
"""
Read all available lines from the queue, concatenated into a single string.
"""
out = ""
while True:
try:
out += self.get_nowait()
except Empty:
break
return out
def readline(self, timeout=None):
""" Read a single line from the queue.
"""
# we break this up into multiple short reads to allow keyboard
# interrupts
start = time.time()
ret = ""
while True:
if timeout is not None:
remaining = start + timeout - time.time()
if remaining <= 0:
return ""
else:
remaining = 1
try:
return self.get(timeout=min(0.1, remaining))
except Empty:
pass