How to get the return value from a thread in python?
One way I've seen is to pass a mutable object, such as a list or a dictionary, to the thread's constructor, along with a an index or other identifier of some sort. The thread can then store its results in its dedicated slot in that object. For example:
def foo(bar, result, index): print 'hello {0}'.format(bar) result[index] = "foo"from threading import Threadthreads = [None] * 10results = [None] * 10for i in range(len(threads)): threads[i] = Thread(target=foo, args=('world!', results, i)) threads[i].start()# do some other stufffor i in range(len(threads)): threads[i].join()print " ".join(results) # what sound does a metasyntactic locomotive make?
If you really want join()
to return the return value of the called function, you can do this with a Thread
subclass like the following:
from threading import Threaddef foo(bar): print 'hello {0}'.format(bar) return "foo"class ThreadWithReturnValue(Thread): def __init__(self, group=None, target=None, name=None, args=(), kwargs={}, Verbose=None): Thread.__init__(self, group, target, name, args, kwargs, Verbose) self._return = None def run(self): if self._Thread__target is not None: self._return = self._Thread__target(*self._Thread__args, **self._Thread__kwargs) def join(self): Thread.join(self) return self._returntwrv = ThreadWithReturnValue(target=foo, args=('world!',))twrv.start()print twrv.join() # prints foo
That gets a little hairy because of some name mangling, and it accesses "private" data structures that are specific to Thread
implementation... but it works.
For python3
class ThreadWithReturnValue(Thread): def __init__(self, group=None, target=None, name=None, args=(), kwargs={}, Verbose=None): Thread.__init__(self, group, target, name, args, kwargs) self._return = None def run(self): print(type(self._target)) if self._target is not None: self._return = self._target(*self._args, **self._kwargs) def join(self, *args): Thread.join(self, *args) return self._return
FWIW, the multiprocessing
module has a nice interface for this using the Pool
class. And if you want to stick with threads rather than processes, you can just use the multiprocessing.pool.ThreadPool
class as a drop-in replacement.
def foo(bar, baz): print 'hello {0}'.format(bar) return 'foo' + bazfrom multiprocessing.pool import ThreadPoolpool = ThreadPool(processes=1)async_result = pool.apply_async(foo, ('world', 'foo')) # tuple of args for foo# do some other stuff in the main processreturn_val = async_result.get() # get the return value from your function.
In Python 3.2+, stdlib concurrent.futures
module provides a higher level API to threading
, including passing return values or exceptions from a worker thread back to the main thread:
import concurrent.futuresdef foo(bar): print('hello {}'.format(bar)) return 'foo'with concurrent.futures.ThreadPoolExecutor() as executor: future = executor.submit(foo, 'world!') return_value = future.result() print(return_value)