it-swarm.com.de

wie erhalte ich den Rückgabewert von einem Thread in Python?

Wie erhalte ich den Wert 'foo', der vom Ziel des Threads zurückgegeben wird? 

from threading import Thread

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

thread = Thread(target=foo, args=('world!',))
thread.start()
return_value = thread.join()

Der oben gezeigte "offensichtliche Weg" funktioniert nicht: thread.join() hat None zurückgegeben.

231
wim

FWIW, das Modul multiprocessing verfügt dazu über eine Nice-Schnittstelle mit der Klasse Pool. Und wenn Sie bei Threads und nicht bei Prozessen bleiben möchten, können Sie einfach die Klasse multiprocessing.pool.ThreadPool als Drop-In-Ersatz verwenden.

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.
225
Jake Biesinger

Eine Möglichkeit, die ich gesehen habe, besteht darin, ein veränderbares Objekt, z. B. eine Liste oder ein Wörterbuch, zusammen mit einem Index oder einem anderen Bezeichner an den Konstruktor des Threads zu übergeben. Der Thread kann dann seine Ergebnisse in seinem dedizierten Slot in diesem Objekt speichern. Zum Beispiel:

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))
    threads[i].start()

# do some other stuff

for i in range(len(threads)):
    threads[i].join()

print " ".join(results)  # what sound does a metasyntactic locomotive make?

Wenn Sie wirklich möchten, dass join() den Rückgabewert der aufgerufenen Funktion zurückgibt, können Sie dies mit einer Thread-Unterklasse wie der folgenden tun:

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

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

twrv.start()
print twrv.join()   # prints foo

Das wird durch einige Namensveränderungen etwas haarig und es greift auf "private" Datenstrukturen zu, die für die Thread-Implementierung spezifisch sind ... aber es funktioniert.

Für 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
163
kindall

Jakes Antwort ist gut, aber wenn Sie keinen Threadpool verwenden möchten (Sie wissen nicht, wie viele Threads Sie benötigen, sondern erstellen sie nach Bedarf), ist die integrierte Funktion zum Übertragen von Informationen zwischen Threads eine gute Möglichkeit Queue.Queue Klasse, da sie Thread-Sicherheit bietet.

Ich habe den folgenden Dekorator erstellt, damit er sich ähnlich wie der Threadpool verhält:

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)
        q.put(ret)

    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.start()
        t.result_queue = q        
        return t

    return wrap

Dann verwenden Sie es einfach als:

@threaded
def long_task(x):
    import time
    x = x + 5
    time.sleep(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

Die dekorierte Funktion erstellt bei jedem Aufruf einen neuen Thread und gibt ein Thread-Objekt zurück, das die Warteschlange enthält, die das Ergebnis empfängt.

UPDATE

Es ist schon eine Weile her, dass ich diese Antwort gepostet habe, aber es werden immer noch Aufrufe angezeigt, sodass ich dachte, ich würde sie aktualisieren, um die Vorgehensweise in neueren Versionen von Python widerzuspiegeln:

Python 3.2 wurde im Modul concurrent.futures hinzugefügt, das eine übergeordnete Schnittstelle für parallele Aufgaben bietet. Es enthält ThreadPoolExecutorund ProcessPoolExecutorname__, sodass Sie einen Thread oder einen Prozesspool mit derselben API verwenden können.

Ein Vorteil dieser API besteht darin, dass beim Senden einer Aufgabe an einen Executorein FutureNAME _ -Objekt zurückgegeben wird, das mit dem Rückgabewert des aufrufbaren Objekts vervollständigt wird, das Sie übergeben.

Dies macht das Anhängen eines queue-Objekts überflüssig, was den Decorator erheblich vereinfacht:

_DEFAULT_POOL = ThreadPoolExecutor()

def threadpool(f, executor=None):
    @wraps(f)
    def wrap(*args, **kwargs):
        return (executor or _DEFAULT_POOL).submit(f, *args, **kwargs)

    return wrap

Dies verwendet einen standardmäßigen Modul-Threadpool-Executor , wenn einer nicht übergeben wird.

Die Verwendung ist der vorherigen sehr ähnlich:

@threadpool
def long_task(x):
    import time
    x = x + 5
    time.sleep(5)
    return x

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

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

Wenn Sie Python 3.4+ verwenden, besteht eine sehr schöne Eigenschaft bei der Verwendung dieser Methode (und von Future-Objekten im Allgemeinen) darin, dass die zurückgegebene Zukunft in ein asyncio.Future umgewandelt werden kann = mit asyncio.wrap_future . Dies macht es einfach mit Coroutinen zu arbeiten:

result = await asyncio.wrap_future(long_task(10))

Wenn Sie keinen Zugriff auf das zugrunde liegende Objekt concurrent.Future benötigen, können Sie den Zeilenumbruch in den Dekorator einschließen:

_DEFAULT_POOL = ThreadPoolExecutor()

def threadpool(f, executor=None):
    @wraps(f)
    def wrap(*args, **kwargs):
        return asyncio.wrap_future((executor or _DEFAULT_POOL).submit(f, *args, **kwargs))

    return wrap

Wann immer Sie einen CPU-intensiven oder blockierenden Code aus dem Event-Loop-Thread entfernen müssen, können Sie ihn in eine dekorierte Funktion einfügen:

@threadpool
def some_long_calculation():
    ...

# this will suspend while the function is executed on a threadpool
result = await some_long_calculation()
77
bj0

Eine weitere Lösung, bei der der vorhandene Code nicht geändert werden muss:

import Queue
from threading import Thread

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

que = Queue.Queue()

t = Thread(target=lambda q, arg1: q.put(foo(arg1)), args=(que, 'world!'))
t.start()
t.join()
result = que.get()
print result

Es kann auch leicht an eine Umgebung mit mehreren Threads angepasst werden:

import Queue
from threading import Thread

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

que = Queue.Queue()
threads_list = list()

t = Thread(target=lambda q, arg1: q.put(foo(arg1)), args=(que, 'world!'))
t.start()
threads_list.append(t)

# Add more threads here
...
threads_list.append(t2)
...
threads_list.append(t3)
...

# Join all the threads
for t in threads_list:
    t.join()

# Check thread's return value
while not que.empty():
    result = que.get()
    print result
24
Arik

Antwort von Parris/kindall join/return auf Python 3 portiert:

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=None, *, daemon=None):
        Thread.__init__(self, group, target, name, args, kwargs, daemon=daemon)

        self._return = None

    def run(self):
        if self._target is not None:
            self._return = self._target(*self._args, **self._kwargs)

    def join(self):
        Thread.join(self)
        return self._return


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

twrv.start()
print(twrv.join())   # prints foo

Beachten Sie, dass die Thread-Klasse in Python 3 unterschiedlich implementiert ist.

15
GuySoft

Ich habe die Antwort von Kindall gestohlen und es ein bisschen aufgeräumt.

Der Schlüsselteil ist das Hinzufügen von * args und ** kwargs zu join (), um das Timeout zu behandeln

class threadWithReturn(Thread):
    def __init__(self, *args, **kwargs):
        super(threadWithReturn, self).__init__(*args, **kwargs)

        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, *args, **kwargs):
        super(threadWithReturn, self).join(*args, **kwargs)

        return self._return

AKTUALISIERTE ANTWORT UNTEN

Dies ist meine am weitesten verbreitete Antwort, daher habe ich mich für ein Update mit Code entschieden, der sowohl für py2 als auch für py3 läuft.

Außerdem sehe ich viele Antworten auf diese Frage, die ein Unverständnis in Bezug auf Thread.join () zeigen. Einige können das Argument timeout nicht vollständig verarbeiten. Es gibt jedoch auch einen Eckpunkt, in dem Sie über Instanzen Bescheid wissen sollten, wenn Sie (1) eine Zielfunktion haben, die None zurückgeben kann, und (2) Sie auch das Argument timeout an join () übergeben. Siehe "TEST 4", um diesen Eckfall zu verstehen.

ThreadWithReturn-Klasse, die mit py2 und py3 funktioniert:

import sys
from threading import Thread
from builtins import super    # https://stackoverflow.com/a/30159479

if sys.version_info >= (3, 0):
    _thread_target_key = '_target'
    _thread_args_key = '_args'
    _thread_kwargs_key = '_kwargs'
else:
    _thread_target_key = '_Thread__target'
    _thread_args_key = '_Thread__args'
    _thread_kwargs_key = '_Thread__kwargs'

class ThreadWithReturn(Thread):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self._return = None

    def run(self):
        target = getattr(self, _thread_target_key)
        if not target is None:
            self._return = target(*getattr(self, _thread_args_key), **getattr(self, _thread_kwargs_key))

    def join(self, *args, **kwargs):
        super().join(*args, **kwargs)
        return self._return

Einige Testbeispiele sind unten aufgeführt:

import time, random

# TEST TARGET FUNCTION
def giveMe(arg, seconds=None):
    if not seconds is None:
        time.sleep(seconds)
    return arg

# TEST 1
my_thread = ThreadWithReturn(target=giveMe, args=('stringy',))
my_thread.start()
returned = my_thread.join()
# (returned == 'stringy')

# TEST 2
my_thread = ThreadWithReturn(target=giveMe, args=(None,))
my_thread.start()
returned = my_thread.join()
# (returned is None)

# TEST 3
my_thread = ThreadWithReturn(target=giveMe, args=('stringy',), kwargs={'seconds': 5})
my_thread.start()
returned = my_thread.join(timeout=2)
# (returned is None) # because join() timed out before giveMe() finished

# TEST 4
my_thread = ThreadWithReturn(target=giveMe, args=(None,), kwargs={'seconds': 5})
my_thread.start()
returned = my_thread.join(timeout=random.randint(1, 10))

Können Sie den Eckpunkt identifizieren, dem wir möglicherweise mit TEST 4 begegnen können?

Das Problem ist, dass wir davon ausgehen, dass giveMe () None zurückgibt (siehe TEST 2), aber wir erwarten auch, dass join () None zurückgibt, wenn es zu einem Timeout kommt.

returned is None bedeutet entweder:

(1) das ist, was giveMe () zurückgegeben hat, oder

(2) Zeitüberschreitung bei join ()

Dieses Beispiel ist trivial, da wir wissen, dass giveMe () immer None zurückgibt. Aber in der realen Welt (wo das Ziel legitimerweise None oder etwas anderes zurückgeben kann) möchten wir explizit prüfen, was passiert ist.

Im Folgenden erfahren Sie, wie Sie diesen Eckpunkt ansprechen:

# TEST 4
my_thread = ThreadWithReturn(target=giveMe, args=(None,), kwargs={'seconds': 5})
my_thread.start()
returned = my_thread.join(timeout=random.randint(1, 10))

if my_thread.isAlive():
    # returned is None because join() timed out
    # this also means that giveMe() is still running in the background
    pass
    # handle this based on your app's logic
else:
    # join() is finished, and so is giveMe()
    # BUT we could also be in a race condition, so we need to update returned, just in case
    returned = my_thread.join()
14
user2426679

Queue verwenden:

import threading, queue

def calc_square(num, out_queue1):
  l = []
  for x in num:
    l.append(x*x)
  out_queue1.put(l)


arr = [1,2,3,4,5,6,7,8,9,10]
out_queue1=queue.Queue()
t1=threading.Thread(target=calc_square, args=(arr,out_queue1))
t1.start()
t1.join()
print (out_queue1.get())
7
user341143

Meine Lösung für das Problem besteht darin, die Funktion und den Thread in eine Klasse zu packen. Erfordert keine Pools, Warteschlangen oder die Übergabe von Variablen vom Typ c. Es ist auch nicht blockierend. Sie überprüfen stattdessen den Status. Siehe Beispiel zur Verwendung am Ende des Codes.

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
        self.data = None
        self.func = self.save_data(func)

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

        return new_func

    def start(self,params):
        self.data = 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)
        self.thread.start()
        return 'started'

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

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

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()
6
Peter Lonjers

Sie können eine Mutable über dem Umfang der Thread-Funktion definieren und das Ergebnis dazu hinzufügen. (Ich habe auch den Code so geändert, dass er mit Python3 kompatibel ist.)

returns = {}
def foo(bar):
    print('hello {0}'.format(bar))
    returns[bar] = 'foo'

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

Dies gibt {'world!': 'foo'} zurück.

Wenn Sie die Funktionseingabe als Schlüssel für Ihr Ergebnisdikt verwenden, wird garantiert, dass jede eindeutige Eingabe einen Eintrag in den Ergebnissen enthält 

2
Thijs D

Unter Berücksichtigung von@imanKommentar zu@JakeBiesingeranswer habe ich es neu zusammengesetzt, um eine unterschiedliche Anzahl von Threads zu haben:

from multiprocessing.pool import ThreadPool

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

numOfThreads = 3 
results = []

pool = ThreadPool(numOfThreads)

for i in range(0, numOfThreads):
    results.append(pool.apply_async(foo, ('world', 'foo'))) # Tuple of args for foo)

# do some other stuff in the main process
# ...
# ...

results = [r.get() for r in results]
print results

pool.close()
pool.join()

Prost,

Kerl.

2
Guy Avraham

Sie können Pool als Pool von Arbeitsprozessen wie folgt verwenden:

from multiprocessing import Pool


def f1(x, y):
    return x*y


if __== '__main__':
    with Pool(processes=10) as pool:
        result = pool.apply(f1, (2, 3))
        print(result)
2
Tung Nguyen

Ich verwende diesen Wrapper, der bequem jede Funktion für das Ausführen einer Thread aktiviert - und sich um den Rückgabewert oder die Ausnahme kümmert. Es wird kein Queue-Overhead hinzugefügt. 

def threading_func(f):
    """Decorator for running a function in a thread and handling its return
    value or exception"""
    def start(*args, **kw):
        def run():
            try:
                th.ret = f(*args, **kw)
            except:
                th.exc = sys.exc_info()
        def get(timeout=None):
            th.join(timeout)
            if th.exc:
                raise th.exc[0], th.exc[1], th.exc[2] # py2
                ##raise th.exc[1] #py3                
            return th.ret
        th = threading.Thread(None, run)
        th.exc = None
        th.get = get
        th.start()
        return th
    return start

Anwendungsbeispiele

def f(x):
    return 2.5 * x
th = threading_func(f)(4)
print("still running?:", th.is_alive())
print("result:", th.get(timeout=1.0))

@threading_func
def th_mul(a, b):
    return a * b
th = th_mul("text", 2.5)

try:
    print(th.get())
except TypeError:
    print("exception thrown ok.")

Hinweise zum Modul threading

Eine komfortable Rückgabewert- und Ausnahmebehandlung einer Thread-Funktion ist ein häufiges Bedürfnis "Pythonic" und sollte vom Modul threading bereits angeboten werden - möglicherweise direkt in der Standardklasse Thread. ThreadPool hat viel zu viel Aufwand für einfache Aufgaben - 3 Threads verwalten, viel Bürokratie. Leider wurde das Layout von Thread ursprünglich aus Java kopiert. vom noch nutzlosen 1. (!) Konstruktorparameter group.

1
kxr

Wie bereits erwähnt, ist der Multiprocessing-Pool viel langsamer als das grundlegende Threading. Die Verwendung von Warteschlangen, wie in einigen Antworten vorgeschlagen, ist eine sehr effektive Alternative. Ich habe es mit Wörterbüchern verwendet, um viele kleine Threads ausführen zu können und mehrere Antworten durch Kombinieren mit Wörterbüchern wiederherzustellen:

#!/usr/bin/env python3

import threading
# use Queue for python2
import queue
import random

LETTERS = 'abcdefghijklmnopqrstuvwxyz'
LETTERS = [ x for x in LETTERS ]

NUMBERS = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

def randoms(k, q):
    result = dict()
    result['letter'] = random.choice(LETTERS)
    result['number'] = random.choice(NUMBERS)
    q.put({k: result})

threads = list()
q = queue.Queue()
results = dict()

for name in ('alpha', 'oscar', 'yankee',):
    threads.append( threading.Thread(target=randoms, args=(name, q)) )
    threads[-1].start()
_ = [ t.join() for t in threads ]
while not q.empty():
    results.update(q.get())

print(results)
1
Yves Dorfsman

join gibt immer None zurück. Ich denke, Sie sollten Thread für Rückgabecodes verwenden.

1
BrainStorm

Eine gewöhnliche Lösung ist, Ihre Funktion foo mit einem Dekorateur wie zu versehen

result = queue.Queue()

def task_wrapper(*args):
    result.put(target(*args))

Dann kann der gesamte Code so aussehen

result = queue.Queue()

def task_wrapper(*args):
    result.put(target(*args))

threads = [threading.Thread(target=task_wrapper, args=args) for args in args_list]

for t in threads:
    t.start()
    while(True):
        if(len(threading.enumerate()) < max_num):
            break
for t in threads:
    t.join()
return result

Hinweis

Ein wichtiges Problem ist, dass die Rückgabewerte unorderred ..__ sein können (der return value wird nicht unbedingt in der queue gespeichert, da Sie eine beliebige thread-sichere Datenstruktur auswählen können.

0
Response777

Definieren Sie Ihr Ziel als
1) nimm ein Argument q
2) Ersetzen Sie alle Anweisungen return foo durch q.put(foo); return.

so eine Funktion

def func(a):
    ans = a * a
    return ans

würde werden

def func(a, q):
    ans = a * a
    q.put(ans)
    return

und dann würden Sie so vorgehen

from Queue import Queue
from threading import Thread

ans_q = Queue()
arg_tups = [(i, ans_q) for i in xrange(10)]

threads = [Thread(target=func, args=arg_tup) for arg_tup in arg_tups]
_ = [t.start() for t in threads]
_ = [t.join() for t in threads]
results = [q.get() for _ in xrange(len(threads))]

Sie können Funktionsdekoratoren/-umhüllungen verwenden, um sie so zu gestalten, dass Sie Ihre vorhandenen Funktionen als target verwenden können, ohne sie zu ändern, aber folgen Sie diesem Grundschema.

0
tscizzle

Warum nicht einfach globale Variable verwenden?

import threading


class myThread(threading.Thread):
    def __init__(self, ind, lock):
        threading.Thread.__init__(self)
        self.ind = ind
        self.lock = lock

    def run(self):
        global results
        with self.lock:
            results.append(self.ind)



results = []
lock = threading.Lock()
threads = [myThread(x, lock) for x in range(1, 4)]
for t in threads:
    t.start()
for t in threads:
    t.join()
print(results)
0
Alexey

Wenn mit dem Aufruf einer Funktion nur "True" oder "False" bestätigt werden soll, ist das Aktualisieren einer globalen Liste eine einfachere Lösung. 

import threading

lists = {"A":"True", "B":"True"}

def myfunc(name: str, mylist):
    for i in mylist:
        if i == 31:
            lists[name] = "False"
            return False
        else:
            print("name {} : {}".format(name, i))

t1 = threading.Thread(target=myfunc, args=("A", [1, 2, 3, 4, 5, 6], ))
t2 = threading.Thread(target=myfunc, args=("B", [11, 21, 31, 41, 51, 61], ))
t1.start()
t2.start()
t1.join()
t2.join()

for value in lists.values():
    if value == False:
        # Something is suspicious 
        # Take necessary action 

Dies ist hilfreich, wenn Sie feststellen möchten, ob einer der Threads einen falschen Status zurückgegeben hat, um die erforderlichen Maßnahmen zu ergreifen. 

0
Sravya

Die Idee von GuySoft ist großartig, aber ich denke, dass das Objekt nicht unbedingt von Thread geerbt werden muss und start () vom Interface entfernt werden kann:

from threading import Thread
import queue
class ThreadWithReturnValue(object):
    def __init__(self, target=None, args=(), **kwargs):
        self._que = queue.Queue()
        self._t = Thread(target=lambda q,arg1,kwargs1: q.put(target(*arg1, **kwargs1)) ,
                args=(self._que, args, kwargs), )
        self._t.start()

    def join(self):
        self._t.join()
        return self._que.get()


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

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

print(twrv.join())   # prints foo
0
pandy.song

Kindalls Antwort in Python3

class ThreadWithReturnValue(Thread):
    def __init__(self, group=None, target=None, name=None,
                 args=(), kwargs={}, *, daemon=None):
        Thread.__init__(self, group, target, name, args, kwargs, daemon)
        self._return = None 

    def run(self):
        try:
            if self._target:
                self._return = self._target(*self._args, **self._kwargs)
        finally:
            del self._target, self._args, self._kwargs 

    def join(self,timeout=None):
        Thread.join(self,timeout)
        return self._return
0
SmartManoj

Sehr einfache Möglichkeit, dies für solche Dummies wie mich zu erledigen:

import queue
import threading

# creating queue instance
q = queue.Queue()

# creating threading class
class AnyThread():
    def __init__ (self):
        threading.Thread.__init__(self)

    def run(self):
        # in this class and function we will put our test target function
        test()

t = AnyThread()

# having our test target function
def test():
    # do something in this function:
    result = 3 + 2
    # and put result to a queue instance
    q.put(result)

for i in range(3): #calling our threading fucntion 3 times (just for example)
    t.run()
    output = q.get() # here we get output from queue instance
    print(output)

>>> 5
>>> 5
>>> 5

hauptsache hier - ist queue Modul. Wir erstellen eine queue.Queue()-Instanz und beziehen sie in unsere Funktion ein. Wir füttern es mit unserem Ergebnis, das wir später über den Thread hinausbringen.

Sehen Sie sich ein weiteres Beispiel mit Argumenten an, die an unsere Testfunktion übergeben wurden:

import queue
import threading

# creating queue instance
q = queue.Queue()

# creating threading class
class AnyThread():
    def __init__ (self):
        threading.Thread.__init__(self)

    def run(self, a, b):
        # in this class and function we will put our execution test function
        test(a, b)

t = AnyThread()

# having our test target function
def test(a, b):
    # do something in this function:
    result = a + b
    # and put result to a queue instance
    q.put(result)

for i in range(3): #calling our threading fucntion 3 times (just for example)
    t.run(3+i, 2+i)
    output = q.get() # here we get output from queue instance
    print(output)

>>> 5
>>> 7
>>> 9
0
Vyachez