valore restituito da filo
-
19-09-2019 - |
Domanda
Come faccio ad avere un filo di restituire una tupla o qualsiasi valore della mia scelta di nuovo al genitore in Python?
Soluzione
Vi suggerisco di un'istanza di un Queue.Queue prima di iniziare il filo e passarlo come uno dei args del filo: prima del thread termina, esso .put
s il risultato sulla coda ha ricevuto come argomento. Il genitore può .get
o .get_nowait
a piacimento.
Le code sono generalmente il modo migliore per organizzare la sincronizzazione dei thread e la comunicazione in Python: sono intrinsecamente thread-safe, veicoli message-passing - il modo migliore per organizzare multitasking in generale -)
!Altri suggerimenti
Se stavi chiamando join () per attendere il filo per completare, si può semplicemente collegare il risultato all'istanza Discussione stesso e poi recuperarlo dal thread principale dopo le unirsi rendimenti ().
D'altra parte, voi non ci dicono come si intende scoprire che il filo è fatto e che il risultato è disponibile. Se si dispone già di un modo di fare che, probabilmente si punta (e noi, se si dovesse dirci) per il modo migliore per ottenere i risultati fuori.
Si dovrebbe passare un'istanza di coda come parametro allora si dovrebbe .Put () l'oggetto di ritorno nella coda. È possibile raccogliere il valore di ritorno via queue.get () qualsiasi oggetto si mette.
Esempio:
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)
Usa per più thread:
#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()
Io uso questa implementazione e funziona benissimo per me. Vi auguro di farlo.
Usa lambda per avvolgere la funzione di thread di destinazione e passare il suo valore di ritorno di nuovo al thread genitore utilizzando un coda . (La funzione di destinazione originale rimane invariato senza parametro coda supplementare.)
Codice di esempio:
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
Sono sorpreso nessuno ha menzionato che si può solo passare un mutabile:
>>> 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}
Forse questo ha importanti problemi di cui sono a conoscenza.
Un altro approccio è quello di passare una funzione callback per il filo. Questo dà un modo semplice, sicuro e flessibile per restituire un valore al genitore, in qualsiasi momento dal nuovo 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()
È possibile utilizzare sincronizzato coda modulo.
Considerate è necessario controllare a informazioni degli utenti da database con un ID di nota:
def check_infos(user_id, queue):
result = send_data(user_id)
queue.put(result)
Ora è possibile ottenere i dati in questo modo:
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()
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
Ebbene, nel modulo filettatura Python, ci sono oggetti condizione che sono associati alle serrature. Un metodo acquire()
restituirà qualsiasi valore restituito dal metodo sottostante. Per maggiori informazioni: Python Condizione Oggetti
In base a suggerimento di jcomeau_ictx. Il più semplice mi sono imbattuto. Requisito qui era quello di ottenere lo stato di uscita staus da tre diversi processi in esecuzione sul server e innescare un altro script, se tutti e tre sono di successo. Questo sembra funzionare bene
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
La seguente funzione di avvolgitore lo avvolgerà una funzione esistente e restituire un oggetto che indica sia al filo (in modo che si può chiamare start()
, join()
, ecc su di esso) e l'accesso / visualizzare il valore eventuale ritorno.
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
Sembra OK, e la classe threading.Thread
sembra essere facilmente esteso (*) con questo tipo di funzionalità, quindi mi chiedo il motivo per cui non è già presente. C'è un difetto con il metodo di cui sopra?
(*) Si noti che la risposta di Husanu per questa domanda fa esattamente questo, sottoclasse threading.Thread
conseguente una versione in cui join()
dà il valore di ritorno.
Per i programmi semplici risposte di cui sopra sembrano un po 'come eccessivo per me. Vorrei en-nicen l'approccio mutevole:
class RetVal:
def __init__(self):
self.result = None
def threadfunc(retVal):
retVal.result = "your return value"
retVal = RetVal()
thread = Thread(target = threadfunc, args = (retVal))
thread.start()
thread.join()
print(retVal.result)