Frage

Wie bekomme ich einen Thread, um ein Tupel oder einen Wert meiner Wahl an die Eltern in Python zurückzugeben?

War es hilfreich?

Lösung

Ich schlage vor, Sie instanziieren a Queue.queue Bevor Sie den Thread starten und ihn als einer der Args des Threads übergeben: Bevor der Thread fertig ist .puts das Ergebnis in der Warteschlange, die es als Argument erhielt. Der Elternteil kann .get oder .get_nowait es nach Belieben.

Warteschlangen sind im Allgemeinen der beste Weg, um die Synchronisation und Kommunikation von Threads in Python zu arrangieren: Sie sind intrinsisch fadensicher, Message-Passing-Fahrzeuge-der beste Weg, Multitasking im Allgemeinen zu organisieren!-)

Andere Tipps

Wenn Sie join () angerufen haben, um auf den Thread zu warten, können Sie das Ergebnis einfach an die Thread -Instanz selbst anschließen und dann nach dem Rückkehr der Juel () aus dem Haupt -Thread abrufen.

Andererseits sagen Sie uns nicht, wie Sie feststellen möchten, dass der Thread erledigt ist und dass das Ergebnis verfügbar ist. Wenn Sie dies bereits dazu haben, wird es Sie (und uns, wenn Sie es uns sagen) wahrscheinlich zum besten Weg, die Ergebnisse zu erzielen.

Sie sollten eine Warteschlange als Parameter übergeben, dann sollten Sie .put () Ihr Rückgabeobjekt in die Warteschlange. Sie können den Rückgabewert über Queue.get (), das Sie ausgeben, sammeln.

Probe:

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)

Verwendung für mehrere 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()

Ich benutze diese Implementierung und sie funktioniert hervorragend für mich. Ich wünschte du tust es.

Verwenden Lambda Um Ihre Ziel -Thread -Funktion zu wickeln und ihren Rückgabewert mit a an den übergeordneten Thread zurückzugeben Warteschlange. (Ihre ursprüngliche Zielfunktion bleibt unverändert ohne zusätzliche Warteschlangenparameter.)

Beispielcode:

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())

Ausgabe:

4

Ich bin überrascht, dass niemand erwähnt hat, dass Sie es einfach ein Veränderbar bestehen könnten:

>>> 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}

Vielleicht hat dies große Probleme, von denen ich nicht weiß.

Ein anderer Ansatz besteht darin, eine Rückruffunktion an den Thread zu übergeben. Dies gibt eine einfache, sichere und flexible Möglichkeit, den Elternteil jederzeit vom neuen Thread zu einem Wert zurückzugeben.

# 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()

Sie können synchronisiert verwenden Warteschlange Modul.
Bedenken Sie, dass Sie einen Benutzer -Infos aus der Datenbank mit einer bekannten ID überprüfen müssen:

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

Jetzt können Sie Ihre Daten wie diese erhalten:

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

Nun, im Python -Threading -Modul gibt es Konditionsobjekte, die Sperren zugeordnet sind. Eine Methode acquire() Wird jeder Wert zurückgeben, der von der zugrunde liegenden Methode zurückgegeben wird. Für mehr Informationen: Python -Zustandsobjekte

Basierend auf dem Vorschlag von JComeau_ictx. Das einfachste, auf das ich gestoßen bin. Voraussetzung war hier, um den Exit -Status staus aus drei verschiedenen Prozessen auf dem Server zu erhalten und ein anderes Skript auszulösen, wenn alle drei erfolgreich sind. Dies scheint gut zu funktionieren

  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

Die folgende Wrapper -Funktion wickelt eine vorhandene Funktion ein und gibt ein Objekt zurück, das beide auf den Thread verweist (damit Sie aufrufen können start(),join(), usw. darauf) sowie Zugriff/Anzeigen des letztendlichen Rückgabewerts.

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

Es sieht gut aus und die threading.Thread Die Klasse scheint leicht (*) mit dieser Art von Funktionalität zu erweitern, also frage ich mich, warum es nicht schon da ist. Gibt es einen Fehler mit der obigen Methode?

(*) Beachten threading.Thread was zu einer Version führt, wo join() gibt den Rückgabewert.

Für einfache Programme sehen die oben genannten Antworten ein bisschen wie Overkill für mich aus. Ich würde den veränderlichen Ansatz nieren:

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)
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top