Return value from stream

How to get a thread to return a tuple or any value of my choice back to the parent element in Python?

+51
python multithreading python-multithreading exit-code
Dec 11 '09 at 6:00
source share
11 answers

I suggest you create an instance of Queue.Queue before starting the stream and pass it as one of the arguments to the stream: until the stream finishes, it .put result in the queue received as an argument. Parent can .get or .get_nowait as desired.

Queues are usually the best way to organize thread synchronization and communication in Python: they are essentially thread safe, message passing vehicles - the best way to organize multitasking in general! -)

+59
Dec 11 '09 at 6:24
source share

If you called join () to wait for the thread to finish, you can simply attach the result to the Thread instance and then extract it from the main thread after join () returns.

On the other hand, you are not telling us how you intend to discover that the stream is done and that the result is available. If you already have a way to do this, it will probably tell you (and us, if you tell) to get the best results.

+12
Dec 12 '09 at 1:27
source share

You must pass the queue instance as a parameter, then you must .put () return the object to the queue. You can collect the return value through queue.get () any object you put.

Example:

 queue = Queue.Queue() thread_ = threading.Thread( target=target_method, name="Thread1", args=[params, queue], ) thread_.start() thread_.join() queue.get() def target_method(self, params, queue): """ Some operations right here """ your_return = "Whatever your object is" queue.put(your_return) 

Use for multiple threads:

 #Start all threads in thread pool for thread in pool: thread.start() response = queue.get() thread_results.append(response) #Kill all threads for thread in pool: thread.join() 

I use this implementation and it works great for me. I want you to do this.

+9
Apr 22 '13 at 10:11
source share

I am surprised that no one mentioned that you can just pass it mutable:

 >>> thread_return={'success': False} >>> from threading import Thread >>> def task(thread_return): ... thread_return['success'] = True ... >>> Thread(target=task, args=(thread_return,)).start() >>> thread_return {'success': True} 

perhaps this has serious problems that I don’t know about.

+6
Dec 07 '15 at 11:51 on
source share

Another approach is to pass the callback function to the stream. This provides a simple, safe, and flexible way to return the value to the parent at any time from the new thread.

 # A sample implementation import threading import time class MyThread(threading.Thread): def __init__(self, cb): threading.Thread.__init__(self) self.callback = cb def run(self): for i in range(10): self.callback(i) time.sleep(1) # test import sys def count(x): print x sys.stdout.flush() t = MyThread(count) t.start() 
+5
Dec 11 '09 at 7:35
source share

Use lambda to wrap the function of the target stream and pass the return value back to the parent stream using the queue . (Your original objective function remains unchanged without an additional queue parameter.)

Code example:

 import threading import queue def dosomething(param): return param * 2 que = queue.Queue() thr = threading.Thread(target = lambda q, arg : q.put(dosomething(arg)), args = (que, 2)) thr.start() thr.join() while not que.empty(): print(que.get()) 

Output:

 4 
+5
Feb 23 2018-11-14T00:
source share

You can use a synchronized queue .
Suppose you need to check user information from a database using a known identifier:

 def check_infos(user_id, queue): result = send_data(user_id) queue.put(result) 

Now you can get your data as follows:

 import queue, threading queued_request = queue.Queue() check_infos_thread = threading.Thread(target=check_infos, args=(user_id, queued_request)) check_infos_thread.start() final_result = queued_request.get() 
+3
Aug 15 '15 at 8:10
source share

POC:

 import random import threading class myThread( threading.Thread ): def __init__( self, arr ): threading.Thread.__init__( self ) self.arr = arr self.ret = None def run( self ): self.myJob( self.arr ) def join( self ): threading.Thread.join( self ) return self.ret def myJob( self, arr ): self.ret = sorted( self.arr ) return #Call the main method if run from the command line. if __name__ == '__main__': N = 100 arr = [ random.randint( 0, 100 ) for x in range( N ) ] th = myThread( arr ) th.start( ) sortedArr = th.join( ) print "arr2: ", sortedArr 
+2
Jan 26 '15 at 21:08
source share

Well, in the Python Threading module there are condition objects associated with locks. One acquire() method returns any value returned from the base method. For More Information: Python State Objects

+1
Dec 11 '09 at 6:10
source share

Based on jcomeau_ictx suggestion. The simplest one I came across. The requirement here was to get exit status status from three different processes running on the server and run another script if all three were successfully executed. It seems to be working fine

  class myThread(threading.Thread): def __init__(self,threadID,pipePath,resDict): threading.Thread.__init__(self) self.threadID=threadID self.pipePath=pipePath self.resDict=resDict def run(self): print "Starting thread %s " % (self.threadID) if not os.path.exists(self.pipePath): os.mkfifo(self.pipePath) pipe_fd = os.open(self.pipePath, os.O_RDWR | os.O_NONBLOCK ) with os.fdopen(pipe_fd) as pipe: while True: try: message = pipe.read() if message: print "Received: '%s'" % message self.resDict['success']=message break except: pass tResSer={'success':'0'} tResWeb={'success':'0'} tResUisvc={'success':'0'} threads = [] pipePathSer='/tmp/path1' pipePathWeb='/tmp/path2' pipePathUisvc='/tmp/path3' th1=myThread(1,pipePathSer,tResSer) th2=myThread(2,pipePathWeb,tResWeb) th3=myThread(3,pipePathUisvc,tResUisvc) th1.start() th2.start() th3.start() threads.append(th1) threads.append(th2) threads.append(th3) for t in threads: print t.join() print "Res: tResSer %s tResWeb %s tResUisvc %s" % (tResSer,tResWeb,tResUisvc) # The above statement prints updated values which can then be further processed 
+1
Jun 17 '16 at 3:36
source share

The next wrapper function will wrap the existing function and return an object that points to the stream (so you can call start() , join() , etc.), as well as access / view its possible return value.

 def threadwrap(func,args,kwargs): class res(object): result=None def inner(*args,**kwargs): res.result=func(*args,**kwargs) import threading t = threading.Thread(target=inner,args=args,kwargs=kwargs) res.thread=t return res def myFun(v,debug=False): import time if debug: print "Debug mode ON" time.sleep(5) return v*2 x=threadwrap(myFun,[11],{"debug":True}) x.thread.start() x.thread.join() print x.result 

It looks fine, and the threading.Thread class seems to be easily extended (*) with such functionality, so I wonder why it doesn't exist yet. Is there a flaw in the above method?

(*) Note that husanu's answer for this question does just that, a subclassification of threading.Thread leads to a version where join() gives the return value.

0
Mar 22 '16 at 2:04 on
source share



All Articles