2017-03-09 8 views
2

Python 3.4.2を使用した非常に簡単なスレッドの例があります。この例では、文字列 "Result"を返す5つのスレッドを作成し、スレッドという配列に追加します。もう1つのforループでは、スレッドが5回反復され、スレッドはxという用語に結合されます。私は['Resut'、 'Result'、 'Result'、 'Result'、 'Result']のようなリストを生成する結果xを出力しようとしていますが、printコマンドはスレッドのタイトルのみを返しますそしてそれが閉じられているという事実。私は明らかにPythonでスレッドを使う方法を誤解しています。誰かがこのテストケースを適切に完了する方法の例を提供できるなら、私は非常に感謝しています。Pythonスレッドからデータにアクセスする方法

import threading 

def Thread_Test(): 
    return ("Result") 

number = 5 
threads = [] 
for i in range(number): 
    Result = threading.Thread(target=Thread_Test) 
    threads.append(Result) 
    Result.start() 

for x in threads: 
    x.join() 
print (x) 
+0

'threading.Thread(target = Thread_Test)'は、スレッドのインスタンスを返します。スレッド名として出力されるスレッド参照の配列を取得します。 – Andrey

+1

キューを使用してデータを収集する必要があります。ここでコンセプトを見つけてください。 https://www.troyfawkes.com/learn-python-multithreading-queues-basics/ – Bhargav

+0

ありがとうございました。 Queは、このようなサンプルコード用に実装されています。 – Jon

答えて

1

import threading 
import Queue 
import timeit 

q = Queue.Queue() 
number = 5 

t1 = timeit.default_timer() 
# Step1: For example, we are running multiple functions normally 
result = [] 
def fun(x): 
    result.append(x) 
    return x 

for i in range(number): 
    fun(i) 
print result ," # normal result" 
print (timeit.default_timer() - t1) 

t2 = timeit.default_timer() 

#Step2: by using threads and queue 

def fun_thrd(x,q): 
    q.put(x) 
    return 
for i in range(number): 
    t1 = threading.Thread(target = fun_thrd, args=(i,q)) 
    t1.start() 
    t1.join() 

thrd_result = [] 

while True: 
    if not q.empty(): 
    thrd_result.append(q.get()) 
    else: 
     break 

print thrd_result , "# result with threads involved" 
print (timeit.default_timer() - t2) 

t3 = timeit.default_timer() 

#step :3 if you want thread to be run without depending on the previous thread 

threads = [] 

def fun_thrd_independent(x,q): 
    q.put(x) 
    return 

def thread_indep(number): 
    for i in range(number): 
     t = threading.Thread(target = fun_thrd_independent, args=(i,q)) 
     t.start() 
     threads.append(t) 

thread_indep(5) 

for j in threads: 
    j.join() 

thread_indep_result = [] 

while True: 
    if not q.empty(): 
     thread_indep_result.append(q.get()) 
    else: 
     break 

print thread_indep_result # result when threads are independent on each other 
print (timeit.default_timer() - t3) 

出力、キューとスレッドについては、以下の簡単な例を見つけてください:それは巨大データの規模

希望に応じて異なります

[0, 1, 2, 3, 4] # normal result 
3.50475311279e-05 
[0, 1, 2, 3, 4] # result with threads involved 
0.000977039337158 
[0, 1, 2, 3, 4] result when threads are independent on each other 
0.000933170318604 

これは役に立ちます。ありがとう

+0

わかりやすい例をありがとう。 1つの質問は、t1.join()がforループの外側にあるべきです。ループが各スレッドの実行を開始し、別のforループ内で結果を結合してはいけません。そうでなければ、次のスレッドを開始する前に1つのスレッドが完了するのを待たなければなりません。 – Jon

+0

@ジョンこれはどちらの方法でもかまいませんが、何が必要なのかによって決まります。スレッドの後にスレッドを実行したいことがあります。 – Bhargav

+0

ありがとうございました。私のサンプルの問題は、計算時間を短縮するためにスレッドを使用して実装しようとしている高度に並列化可能な数値メソッドの単純化に過ぎませんでした。あなたの実装は、実際には通常の結果よりも時間がかかるように見えます。問題にそれを適用すると、速度が上がらず、計算に数秒が追加されます。私はあなたの解決策で何かを誤解していますか? – Jon

4

スレッドを作成してスレッドから値を取得しようとすると、違いがあります。一般的に言えば、スレッド内でreturnを使用して呼び出し元に値を返してはいけません。それはスレッドの仕組みではありません。スレッドオブジェクトを作成するときは、スレッド内で計算された値をプログラムの他の部分に取り込む別の方法を見つけなければなりません。以下は、リストを使用して値を返す方法を示す簡単な例です。

#! /usr/bin/env python3 
import threading 


def main(): 
    # Define a few variables including storage for threads and values. 
    threads_to_create = 5 
    threads = [] 
    results = [] 
    # Create, start, and store all of the thread objects. 
    for number in range(threads_to_create): 
     thread = threading.Thread(target=lambda: results.append(number)) 
     thread.start() 
     threads.append(thread) 
    # Ensure all threads are done and show the results. 
    for thread in threads: 
     thread.join() 
    print(results) 


if __name__ == '__main__': 
    main() 

あなたは絶対にあなたがスレッドのターゲットから値を返す機能を持っていなければならないことを主張する場合、所望の動作を得るために子クラスを使用してthreading.Threadでいくつかのメソッドをオーバーライドすることが可能です。以下は、より高度な使い方を示し、新しいクラスのメソッドrunを継承して上書きしたい場合に、複数のメソッドが変更を必要とする方法を示しています。このコードは完全性のために提供されており、おそらく使用すべきではありません。

#! /usr/bin/env python3 
import sys as _sys 
import threading 


def main(): 
    # Define a few variables including storage for threads. 
    threads_to_create = 5 
    threads = [] 
    # Create, start, and store all of the thread objects. 
    for number in range(threads_to_create): 
     thread = ThreadWithReturn(target=lambda: number) 
     thread.start() 
     threads.append(thread) 
    # Ensure all threads are done and show the results. 
    print([thread.returned for thread in threads]) 


class ThreadWithReturn(threading.Thread): 

    def __init__(self, group=None, target=None, name=None, 
       args=(), kwargs=None, *, daemon=None): 
     super().__init__(group, target, name, args, kwargs, daemon=daemon) 
     self.__value = None 

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

    def _bootstrap_inner(self): 
     try: 
      self._set_ident() 
      self._set_tstate_lock() 
      self._started.set() 
      with threading._active_limbo_lock: 
       threading._active[self._ident] = self 
       del threading._limbo[self] 

      if threading._trace_hook: 
       _sys.settrace(threading._trace_hook) 
      if threading._profile_hook: 
       threading. _sys.setprofile(threading._profile_hook) 

      try: 
       self.__value = True, self.run() 
      except SystemExit: 
       pass 
      except: 
       exc_type, exc_value, exc_tb = self._exc_info() 
       self.__value = False, exc_value 
       if _sys and _sys.stderr is not None: 
        print("Exception in thread %s:\n%s" % 
          (self.name, threading._format_exc()), file=_sys.stderr) 
       elif self._stderr is not None: 
        try: 
         print((
          "Exception in thread " + self.name + 
          " (most likely raised during interpreter shutdown):"), file=self._stderr) 
         print((
          "Traceback (most recent call last):"), file=self._stderr) 
         while exc_tb: 
          print((
           ' File "%s", line %s, in %s' % 
           (exc_tb.tb_frame.f_code.co_filename, 
            exc_tb.tb_lineno, 
            exc_tb.tb_frame.f_code.co_name)), file=self._stderr) 
          exc_tb = exc_tb.tb_next 
         print(("%s: %s" % (exc_type, exc_value)), file=self._stderr) 
        finally: 
         del exc_type, exc_value, exc_tb 
      finally: 
       pass 
     finally: 
      with threading._active_limbo_lock: 
       try: 
        del threading._active[threading.get_ident()] 
       except: 
        pass 

    @property 
    def returned(self): 
     if self.__value is None: 
      self.join() 
     if self.__value is not None: 
      valid, value = self.__value 
      if valid: 
       return value 
      raise value 


if __name__ == '__main__': 
    main() 
関連する問題