質問をすることでしか得られない、回答やアドバイスがある。

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

新規登録して質問してみよう
ただいま回答率
86.12%
Python 3.x

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

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

解決済

Python:threadingの実行結果の保存先について

calendar
calendar

総合スコア4

Python 3.x

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

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

2回答

0グッド

0クリップ

210閲覧

投稿2022/11/15 18:47

以前質問させていただき回答をいただいたのですが、問題をみつけたため質問させていただきます。

実現したいことと前提

ライブラリABC(名前は仮です)のfuncという関数の返り値を1秒以内の時間制限で取得する関数を作りたいです。
具体的には1秒以内で値が返ってきたらその値を出力。
1秒以内に返ってこなければ関数を停止し別の文字列を出力。

func:文字列を返す,実行時間は一瞬で終わることもあれば無限に終わらないこともある

発生している問題・解決方針

ソースコードで指摘している箇所で止まってしまっています。
原因としてはreturn文の箇所でもう一度ABC.funcを実行しなおしているためだと考えています。
スレッドに渡した関数の実行結果をどうにかして保存して置ければ、それをreturnすればよいので解決すると考えています。

該当のソースコード

python

1import threading 2import ABC#ライブラリの名前に意味はないです 3 4#出力結果は文字列 5def thread_func(): 6 txt="hoge" 7 th=threading.Thread(target=ABC.func()) 8 th.start() 9 th.join(1)#1秒間動かす 10 if not th.is_alive():#ABC.funcが停止していればreturnしたい 11 return ABC.func()#ここで停止してしまいます 12 else: 13 return txt 14 15 16

よろしくお願いいたします!

以下のような質問にはグッドを送りましょう

  • 質問内容が明確
  • 自分も答えを知りたい
  • 質問者以外のユーザにも役立つ

グッドが多くついた質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

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

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

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

下記のような質問は推奨されていません。

  • 間違っている
  • 質問になっていない投稿
  • スパムや攻撃的な表現を用いた投稿

適切な質問に修正を依頼しましょう。

otn

2022/11/16 05:02

先の質問とは質問の前提がかなり異なっていますが、こっちが本当の要件だったと言うことですかね。
calendar

2022/11/16 16:02

前回はお世話になりました。ありがとうございました。 参考にさせていただいたコードを実現するために別のメソッドを用意しようと思い作成したのがこちらになります。
otn

2022/11/16 16:09

先の質問は、先の質問に書いてあった要件のための物なので、要件が先の質問と異なると言うことなら、全く新たに考えた方が良いです。

回答2

1

ベストアンサー

threading.Threadで呼んだ関数の返り値を受け取ることはできません。 ですが、いくつか方法はあります。

その1

スレッドはメモリを共有していますので、データの受け渡し用にミュータブルなオブジェクトを関数に渡して、そこに値を入れてもらう方法です。
質問の状況で、ライブラリABCの関数変更できないのであれば、ラッパー(wrapper)を作ります。
ABC.func()が修正できるのであれば、そうするのがいいでしょう。

python

1import threading 2import ABC#ライブラリの名前に意味はないです 3 4def wrap_ABCfunc (result): 5 result.append(ABC.func()) 6 7#出力結果は文字列 8def thread_func(): 9 txt = 'hoge' 10 result = [] 11 th=threading.Thread(target=wrap_ABCfunc(), args=(result,)) 12 th.start() 13 th.join(1)#1秒間動かす 14 if not th.is_alive():#ABC.funcが停止していればreturnしたい 15 return result[0] 16 else: 17 return txt

その2

pythonには、threadingよりも新しい、並列処理用のモジュールがいくつかあり、それらを使うと呼び出した関数の返り値を取得することができます。

concurent.futureモジュールだとたぶんこんな感じ

python

1import concurrent.futures 2 3with concurrent.futures.ThreadPoolExecutor() as executor: 4 future = executor.submit(ABC.hoge) 5 try: 6 return_value = future.result(timeout=1) 7 print(return_value) 8 except concurrent.futures._base.TimeoutError as e: 9 print('hoge')

投稿2022/11/16 02:33

TakaiY

総合スコア10482

spoofy_dragon👍を押しています

良いと思った回答にはグッドを送りましょう。
グッドが多くついた回答ほどページの上位に表示されるので、他の人が素晴らしい回答を見つけやすくなります。

下記のような回答は推奨されていません。

  • 間違っている回答
  • 質問の回答になっていない投稿
  • スパムや攻撃的な表現を用いた投稿

このような回答には修正を依頼しましょう。

回答へのコメント

calendar

2022/11/16 15:57

コードまで記載いただきありがとうございます。 concurrent.futuresに関して勉強を進め記載いただいたコードを参考にしたところ、 実現したいシステムができました。

1

threading.Thread で target に渡す関数の戻り値は無視されます。
source code 該当箇所 Thread.run メソッド内

値を受け渡す方法は

  • 関数内で何処か外側のスコープに渡すか、Queue 等を使い値を受け渡します。
  • concurrent.futures.ThreadPoolExecutor や ProcessPoolExecutor を使うなら

 関数の結果を取り出す result() メソッドに timeout を指定することができます。

  • 外部ライブラリを使う

 タイムアウト時に例外を投げる関数デコレーターやコンテキストマネージャが幾つか有ります。
Pythonの関数をタイムアウトさせるときに便利なライブラリ

スレッドを用いる方法では、タイムアウトの通知はされますが、関数の実行自体は中断されない点に注意してください。
もし時間の掛かる処理を取りやめたい場合は、関数自体を中断可能な設計するか、
multiprocessing.Process と terminate を用いてプロセス自体を終了することになります。

Python の Thread クラスには明示的に強制終了させる API はありません。
(可能ではありますが、内部API呼び出し等をしたり、デバッグが複雑になりお勧めは出来ません)
また、ProcessPoolExecutor で用いる future の cancel メソッドは、
実行スケジュールのキャンセルであって、実行中の関数はキャンセルできない点にも注意。


ABC.func が止まる件については、ABC.func のコードを提示してください。

Thread(target=ABC.func()) target の時点で関数を呼び出している等、
恐らく実行されているコードと掲載のコードが異なるので、
質問には問題の現象が再現できるコードを掲載してください。

投稿2022/11/16 02:24

編集2022/11/16 02:58
teamikl

総合スコア8538

spoofy_dragon👍を押しています

良いと思った回答にはグッドを送りましょう。
グッドが多くついた回答ほどページの上位に表示されるので、他の人が素晴らしい回答を見つけやすくなります。

下記のような回答は推奨されていません。

  • 間違っている回答
  • 質問の回答になっていない投稿
  • スパムや攻撃的な表現を用いた投稿

このような回答には修正を依頼しましょう。

回答へのコメント

calendar

2022/11/16 16:01

丁寧にリンクまで記載いただきありがとうございます。 ProcessPoolExecutorでのfutureのcancelメソッドについての解説もありがとうございます。 そこで一度悩んでしまったのでアンサーを読み返したとき助かりました。
teamikl

2022/11/16 16:56

スレッドやProcessPoolExecutorだけでは 「関数を停止し」の部分が出来ない点に注意してください。 タイムアウトによりメイン側の待機状態は解除されますが、 ABC.func 関数の実行自体は続きます。

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

ただいまの回答率
86.12%

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

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

質問する

関連した質問

同じタグがついた質問を見る

Python 3.x

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

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。