how to get the return value from a thread in python?

How can I access that return value 'foo' from the thread?

def foo(bar):
  print 'hello {0}'.format(bar)
  return 'foo'

from threading import Thread
t = Thread(target=foo, args=('world!',))
x = t.join()
print x

The one obvious way to do it, above, seems to just return None in x.

share|improve this question
  add comment

5 Answers

up vote11down voteaccepted

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 themultiprocessing.pool.ThreadPool class as a drop-in replacement.

def foo(bar, baz):
  print 'hello {0}'.format(bar)
  return 'foo' + baz

from multiprocessing.pool import ThreadPool
pool = ThreadPool(processes=1)

async_result = pool.apply_async(foo, ('world', 'foo')) # tuple of args for foo

# do some other stuff in the main process

return_val = async_result.get()  # get the return value from your function.
share|improve this answer
this is the best answer as it's non-intrusive –  Jayen yesterday
add comment

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 Thread

threads = [None] * 10
results = [None] * 10

for i in range(len(threads)):
    threads[i] = Thread(target=foo, args=('world!', results, i))

# do some other stuff

for i in range(len(threads)):

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 aThread subclass like the following:

from threading import Thread

def 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,
    def join(self):
        return self._return

twrv = ThreadWithReturnValue(target=foo, args=('world!',))

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.

share|improve this answer
thanks, i can see that that would be fine as a workaround, but it changes the function definition so that it doesn't really return anything. i wanted to know in my original case, where does that 'foo' actually go...? – wim Aug 2 '11 at 3:53 
@wim: Return values go somewhere only if you put them somewhere. Unfortunately, in the case of Thread, all that happens inside the class -- the default run() method does not store off the return value, so you lose it. You could write your own Thread subclass to handle this, though. I've taken a whack at it in my message. –  kindall Aug 3 '11 at 1:20
cool, thanks for the example! i wonder why Thread was not implemented with handling a return value in the first place, it seems like an obvious enough thing to support. –  wim Aug 3 '11 at 1:28
add comment

Jake's answer is good, but if you don't want to use a threadpool (you don't know how many threads you'll need, but create them as needed) then a good way to transmit information between threads is the built-inQueue.Queue class, as it offers thread safety.

I created the following decorator to make it act in a similar fashion to the threadpool:

def threaded(f, daemon=False):
    import Queue

    def wrapped_f(q, *args, **kwargs):
        '''this function calls the decorated function and puts the 
        result in a queue'''
        ret = f(*args, **kwargs)

    def wrap(*args, **kwargs):
        '''this is the function returned from the decorator. It fires off
        wrapped_f in a new thread and returns the thread object with
        the result queue attached'''

        q = Queue.Queue()

        t = threading.Thread(target=wrapped_f, args=(q,)+args, kwargs=kwargs)
        t.daemon = daemon
        t.result_queue = q        
        return t

    return wrap

Then you just use it as:

def long_task(x):
    import time
    x = x + 5
    return x

# does not block, returns Thread object
y = long_task(10)
print y

# this blocks, waiting for the result
result = y.result_queue.get()
print result

The decorated function creates a new thread each time it's called and returns a Thread object that contains the queue that will receive the result.

share|improve this answer
I can't seem to get this to work; I get an error stating AttributeError: 'module' object has no attribute 'Lock' this appears to be emanating from the line y = long_task(10)... thoughts? – sadmicrowave Sep 13 at 2:26
The code doesn't explicitly use Lock, so the problem could be somewhere else in your code. You may want to post a new SO question about it –  bj0 Sep 14 at 4:18
add comment

join always return None, i think you should subclass Thread to handle return codes and so.

share|improve this answer
  add comment

My solution to the problem is to wrap the function and thread in a class. Does not require using pools,queues, or c type variable passing. It is also non blocking. You check status instead. See example of how to use it at end of code.

import threading

class ThreadWorker():
    The basic idea is given a function create an object.
    The object can then run the function in a thread.
    It provides a wrapper to start it,check its status,and get data out the function.
    def __init__(self,func):
        self.thread = None = None
        self.func = self.save_data(func)

    def save_data(self,func):
        '''modify function to save its returned data'''
        def new_func(*args, **kwargs):
  *args, **kwargs)

        return new_func

    def start(self,params): = None
        if self.thread is not None:
            if self.thread.isAlive():
                return 'running' #could raise exception here

        #unless thread exists and is alive start or restart it
        self.thread = threading.Thread(target=self.func,args=params)
        return 'started'

    def status(self):
        if self.thread is None:
            return 'not_started'
            if self.thread.isAlive():
                return 'running'
                return 'finished'

    def get_results(self):
        if self.thread is None:
            return 'not_started' #could return exception
            if self.thread.isAlive():
                return 'running'

def add(x,y):
    return x +y

add_worker = ThreadWorker(add)
print add_worker.start((1,2,))
print add_worker.status()
print add_worker.get_results()
share|improve this answer
  add comment
个人分类: python
想对作者说点什么? 我来说一句



how to get the return value from a thread in python?