スレッドから戻り値を取得するにはどうすればいいですか? 質問する

スレッドから戻り値を取得するにはどうすればいいですか? 質問する

以下の関数fooは文字列を返します。スレッドのターゲットから返される'foo'値を取得するにはどうすればよいですか?'foo'

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

上記の「1 つの明白な方法」は機能しません。thread.join()が返されますNone

ベストアンサー1

私が見た方法の 1 つは、リストや辞書などの可変オブジェクトを、インデックスやその他の何らかの識別子とともにスレッドのコンストラクタに渡すというものです。スレッドは、その結果をそのオブジェクトの専用スロットに格納できます。たとえば、次のようになります。

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?

join()呼び出された関数の戻り値を実際に返したい場合は、Thread次のようなサブクラスを使用してこれを行うことができます。

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

名前のマングリングが原因で少し面倒になり、Thread実装に固有の「プライベート」データ構造にアクセスしますが、機能します。

Python 3の場合:

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

おすすめ記事