647 Stimmen

Wie erhält man den Rückgabewert eines Threads in Python?

Die Funktion foo unten gibt eine Zeichenkette zurück 'foo' . Wie kann ich den Wert erhalten 'foo' die 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()

Die oben gezeigte "offensichtliche Lösung" funktioniert nicht: thread.join() zurückgegeben None .

7voto

Guy Avraham Punkte 3086

Unter Berücksichtigung von @iman Kommentar zu @JakeBiesinger Antwort Ich habe sie so umgestaltet, dass sie eine unterschiedliche Anzahl von Threads enthält:

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

6voto

kxr Punkte 3782

Ich verwende diesen Wrapper, der bequem jede Funktion zur Ausführung in einer Thread - und kümmert sich um seinen Rückgabewert oder seine Ausnahme. Es fügt keine Queue Overhead.

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

Beispiele für die Verwendung

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.")

Anmerkungen zu threading Modul

Komfortable Rückgabewert- und Ausnahmebehandlung einer threaded Funktion ist ein häufiges "pythonisches" Bedürfnis und sollte eigentlich schon von der threading Modul - möglicherweise direkt im Standard Thread Klasse. ThreadPool hat viel zu viel Overhead für einfache Aufgaben - 3 Verwaltungs-Threads, viel Bürokratie. Leider Thread wurde ursprünglich von Java kopiert - was man z.B. an dem immer noch nutzlosen 1. (!) Konstruktorparameter sieht group .

6voto

Pithikos Punkte 16676

Basierend auf was kindall erwähnt, hier ist die allgemeinere Lösung, die mit Python3 funktioniert.

import threading

class ThreadWithReturnValue(threading.Thread):
    def __init__(self, *init_args, **init_kwargs):
        threading.Thread.__init__(self, *init_args, **init_kwargs)
        self._return = None
    def run(self):
        self._return = self._target(*self._args, **self._kwargs)
    def join(self):
        threading.Thread.join(self)
        return self._return

使用方法

        th = ThreadWithReturnValue(target=requests.get, args=('http://www.google.com',))
        th.start()
        response = th.join()
        response.status_code  # => 200

5voto

BrainStorm Punkte 2026

join immer zurückkehren None Ich denke, Sie sollten die Unterklasse Thread um Rückgabecodes und so weiter zu behandeln.

4voto

Thijs D Punkte 752

Sie können eine mutable oberhalb des Geltungsbereichs der threaded function definieren und das Ergebnis in diese einfügen. (Ich habe den Code auch geändert, damit er mit Python 3 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 ergibt {'world!': 'foo'}

Wenn Sie die Funktion input als Schlüssel für Ihr Ergebnisdiktat verwenden, ist garantiert, dass jede eindeutige Eingabe einen Eintrag im Ergebnisdiktat ergibt

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X