🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Q&A

2回答

3206閲覧

【python】concurrent.futuresを使った並列処理における戻り値の利用方法について

Uka

総合スコア28

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

0グッド

0クリップ

投稿2020/12/10 11:38

編集2020/12/10 11:56

前提・実現したいこと

下記のソースコードにおいて、func1とfunc2を並列処理させ、func1とfunc2それぞれの戻り値を使ってfunc3,func4を実行したいと考えています。その際、func3,func4についてもできれば並列処理させたいと考えていますが、func3,func4の中でfunc1とfunc2の戻り値をどのように利用すればよいのかがわかりません。アドバイスいただけましたらありがたいです。よろしくお願いいたします。

該当のソースコード

#MCP3208 from concurrent.futures import ThreadPoolExecutor import RPi.GPIO as GPIO #GPIOに関するコードは割愛 def func1(): while True: while (GPIO.input(up_pin) == 1): while (GPIO.input(down_pin) == 1): while (GPIO.input(measurement_pin) == 1): num = 0 while num <=500:        num += 1 t_seg = ... time.sleep(0.05) return num, t_seg def func2(): while True:     for i in range(5000): count = ... time.sleep(0.001) return count def func3(): x=analog_read(0) #func1の戻り値(num)と*func2の戻り値(count)を使って処理したい #calc_a=x*num*count*... をこの関数の戻り値としたい def func4(): y=analog_read(1) #func1の戻り値(num,t_seg)を使って処理したい #calc_b=y*count*... をこの関数の戻り値としたい if __name__=="__main__": with ThreadPoolExecutor(max_workers=2, thread_name_prefix="thread1") as executor: for _ in range(1000): executor.submit(func1) executor.submit(func2)

試したこと

func3,func4がないソースコードでは、並列処理できていることを確認できています。
(その際、func1およびfunc2の戻り値は"なし"にしています)

補足情報(FW/ツールのバージョンなど)

ここにより詳細な情報を記載してください。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

  • future = executor.submit(func)
  • future.add_done_callback で関数の実行が終わった後に呼び出される関数を登録
  • 引数future の result() で戻り値を取り出せます
  • callback は複数指定できます

python

1 2import time 3from concurrent.futures import ThreadPoolExecutor 4 5def func1(): 6 time.sleep(3) 7 return 5, 10 8 9def func2(future): 10 num, count = future.result() 11 print(count) 12 13def func3(future): 14 num, count = future.result() 15 print(num) 16 17with ThreadPoolExecutor() as e: 18 future = e.submit(func1) 19 future.add_done_callback(func2) 20 future.add_done_callback(func3)

投稿2020/12/10 11:58

teamikl

総合スコア8729

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

concurrent.futuresのドキュメントやqiitaを参考にして書いてみました。参考になれば。

python

1import concurrent.futures 2from concurrent.futures import ThreadPoolExecutor 3from time import sleep 4 5def func1(): 6 print("in func1().") 7 num = 1 8 t_seg = 2 9 sleep(3) 10 print("out func1().") 11 return num, t_seg 12 13def func2(): 14 print("in func2().") 15 count = 3 16 sleep(2) 17 print("out func2().") 18 return count 19 20def func3(num, t_seg): 21 print("in func3(). num={} t_seg={}".format(num, t_seg)) 22 sleep(4) 23 print("out func3().") 24 return True 25 26def func4(count): 27 print("in func4(). count={}".format(count)) 28 sleep(2) 29 print("out func4().") 30 return False 31 32if __name__ == "__main__": 33 with ThreadPoolExecutor(max_workers=2, thread_name_prefix="thread1") as executor: 34 futures = [] 35 futures.append(executor.submit(func1)) # return are num, t_seg 36 futures.append(executor.submit(func2)) # return is count 37 concurrent.futures.wait(futures) 38 print([f.result() for f in futures]) 39 40 num = futures[0].result()[0] 41 t_seg = futures[0].result()[1] 42 count = futures[1].result() 43 futures = [] 44 futures.append(executor.submit(func3, num, t_seg)) 45 futures.append(executor.submit(func4, count)) 46 concurrent.futures.wait(futures) 47 print([f.result() for f in futures]) 48

実行結果です。

result

1in func1(). 2in func2(). 3out func2(). 4out func1(). 5[(1, 2), 3] 6in func3(). num=1 t_seg=2 7in func4(). count=3 8out func4(). 9out func3(). 10[True, False]

投稿2020/12/10 13:50

ikapy

総合スコア1167

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Uka

2020/12/11 10:00 編集

@ikapyさん 詳細にコード教えてくださりありがとうございます。 いただいたコードを参考に組みなおしていますが、whileやfor文を入れているせいか、戻り値の受け渡しがうまくいきません( 上記コードのprint("out func3().")と print("out func3().")が表示されません、当然print([f.result() for f in futures])も表示されません)このあたりはいろいろやってみようと思います!
ikapy

2020/12/11 11:49

そうですか。わたくしの場合は、質問者さんのものを単純化したものですからね。でもこれはこれで提示した甲斐があると思っています。 リアルでは提示されたGPIOはまたこれで壁があるかもしれません。でもこのコンカレント技法は、私が暇で行っているスクレイピングに応用ができるのはでと思っていて良かったです。 concurrent.futuresのソースは見ていませんが、別プロセスとするのであれば理解が早いのですがそこらへんがよくわかってません。 マルチスレッド、マルチプロセスの処理はリソースの扱いが難しいです(concurrentが別プロセスに展開するのであれば扱いやすいと思っています)。 実際には、func1、func2を単体として確実に動作確認するのが良いかもしれません。本ケースでは、デバッガを使うことはありませんでしたが、コンカレントではデバッガの利用も難しいかもしれません。 一つ々、積み重ねていくのが大切だと思います。 頑張ってくださいませ。
ikapy

2020/12/11 11:58

追記。 こういう場合は、ダサくても要所々にprintで情報出力してください。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.36%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問