I need to be able to capture the return value of a function and its stdout
/stderr
in a threaded context. Currently, I'm evaluating a number of subclasses (my_class_foo
, my_class_bar
) based on this base class (my_base_class
) by invoking the is_true
method in each subclass.
I'd like to be able to capture both the return value from each is_true
as well as the stdout
/stderr
. The current solution below works in a non-threaded or non-multiprocess context. However, it relies on redirecting the stdout
/stderr
which obviously won't work if I'm evaluating more than one of these subclasses in parallel.
I've looked at the concurrent.futures
and multiprocess
and subprocess
packages and can't figure out a solution.
I'm trying to avoid using loggers so that users can just rely on printing to stdout
instead of using an explicit method.
I would like to execute the is_true
methods from my_class_foo
and my_class_bar
and in parallel and be able to capture the stdout
messages with each class' return value.
class my_class_foo(my_base_class):
def is_true(self):
print('foo')
return True
class my_class_bar(my_base_class):
def is_true(self):
print('bar')
return False
class my_base_class(object):
def is_true(self):
Raise NotImplementedError
def evaluate_node_is_true(self):
with Capturing() as is_true_stdout:
node_is_true = self.is_true()
self.output = ''.join(is_true_stdout)
class Capturing(list):
"""
Context manager for capturing the stdout of the is_true() function call
"""
def __enter__(self):
self._stdout = sys.stdout
self._stderr = sys.stderr
sys.stdout = self._stringio_out = io.StringIO()
sys.stderr = self._stringio_err = io.StringIO()
return self
def __exit__(self, *args):
self.extend(self._stringio_out.getvalue().splitlines())
self.extend(self._stringio_err.getvalue().splitlines())
del self._stringio_out
del self._stringio_err
sys.stdout = self._stdout
sys.stderr = self._stderr