2009-08-04 18 views
5

Pythonで予期せず長時間実行されるスレッドを終了するには、どのような方法が推奨されますか?私は シグナルとスレッドの両方が 同じプログラムで使用されている場合、いくつか注意が必要長時間実行しているPythonスレッドを終了する

以来、SIGALRMを使用することはできません。 への基本的なことは、信号とスレッドを同時に使用することを覚えておいてください。 signal()操作を実行します。 実行中です。どのスレッドもalarm()、getsignal()、pause()、 setitimer()またはgetitimer()を実行できます。 (これは、基本となるスレッド 実装が の送信がサポートされていた場合でも、Pythonの信号 モジュールによって強制されるだけ メインスレッドが新しい信号 ハンドラを設定することができ、メインスレッドは信号 を受信する 一つだけになります個々のスレッドへのシグナル)。この は、信号が のスレッド間通信の手段として使用できないことを意味します。代わりに、ロックを使用してください。

更新:私のケースブロックの各スレッド - urllib2モジュールを使用してWebページをダウンロードしていますが、動作が非常に遅いサイトでは時間がかかることがあります。だからこそ遅いスレッドを終了したいのですが

答えて

6

ブロッキングコール内のスレッドを突然終了させることは実現不可能なため、可能な場合は、スレッドを使用しないようにして、このような問題のない他のマルチタスクメカニズムを使用しないようにしてください。

OPの特殊なケース(スレッドの仕事はウェブページをダウンロードすることですが、いくつかのスレッドは不正なサイトによって永久にブロックされます)は理想的なソリューションはtwistedです。他のケースでは、multiprocessingが良いかもしれません。

もっと一般的に言えば、スレッドで解決できない問題が発生した場合、少なくともCPythonではスレッドが不適切であるタスクをスレッドで実行しようとするヒロイックメジャーを試すのではなく、他のマルチタスクメカニズムに切り替えることをおすすめします。

1

コードを制御できないスレッドを殺そうとすると、スレッドがブロッキングコール中であるかどうかによって異なります。スレッドが適切にブロックしている場合の私の経験では、これを行うための推奨された移植可能な方法はありません。

標準ライブラリ(multiprocessing.manager私があなたを見ている)のコードを、終了条件なしでコード化されたループで処理しようとしているとき、これに対して実行しました。

そこにはインターストラップ可能なスレッド実装がいくつかありますが(see here for an example)、スレッドコードの制御権を自分で持っている場合は、条件変数でそれらを混在させることができるはずですある種の。

1

同期オブジェクトを使用し、スレッドに終了を要求します。基本的には、これの協力的な取り扱いを書いてください。

Pythonインタプリタの下のスレッドをヤンクし始めると、あらゆる種類の奇妙なことが起こる可能性があります。また、Pythonだけでなく、ほとんどのランタイムにこの問題があります。

たとえば、スレッドがファイルを開いた後でスレッドを終了させると、アプリケーションが終了するまでファイルが閉じられることはありません。

+0

問題はあなたが時間がかかりすぎる(例えばurllib.read()、ある場合にはタイムアウトを無視する)中断したい。 – kolinko

+1

あなたはそれを独自のスレッドで実行すると、単にそれを待つことを止められませんか?最終的には完了/失敗/終了し、それだけで死ぬでしょうか? –

5

Alex Martelliが示唆したように、マルチプロセッシングモジュールを使用することができます。これはThreadingモジュールと非常によく似ているので、簡単に始めることができます。あなたのコードは次のようになります。

import multiprocessing 

def get_page(*args, **kwargs): 
    # your web page downloading code goes here 

def start_get_page(timeout, *args, **kwargs): 
    p = multiprocessing.Process(target=get_page, args=args, kwargs=kwargs) 
    p.start() 
    p.join(timeout) 
    if p.is_alive(): 
     # stop the downloading 'thread' 
     p.terminate() 
     # and then do any post-error processing here 

if __name__ == "__main__": 
    start_get_page(timeout, *args, **kwargs) 

もちろん、コードをダウンロードするコードの戻り値を取得する必要があります。そのためには、マルチプロセッシングを使用することができます。パイプまたはマルチプロセッシング.Queue(またはマルチプロセッシングで利用可能な他の方法)。さらに詳しい情報と、http://docs.python.org/library/multiprocessing.htmlで確認できるサンプルがあります。

最後に、マルチプロセッシングモジュールはPython 2.6に含まれています。は、PyPIでのpython 2.5および2.4のため

を(あなたはeasy_installを

マルチプロセッシング

を使用することができます)、または単には、PyPIやダウンロードを訪問し、手動でパッケージをインストールも可能です。

注:これはしばらく前に投稿されたことを認識しています。私はこれに似た問題を抱えていて、ここで遭遇し、Alex Martelliの提案を見ました。私の問題のためにそれを実装し、それを共有することに決めました。 (私は正しい方向に私を指しているアレックスに感謝したい)

+0

私はまったく同じ問題を抱えていますが、プロセスはちょっとしたトリックをやっていません。メモリが多すぎて、100プロセスが同時に実行されていて、4GB RAMが難しいです。 – kolinko

関連する問題