2016-04-15 16 views
1

私はマルチプロセッシングについての詳細を理解しようとしているマルチプロセッシング・スレッドプールは

のWindows 7上のPython 3.4を実行しているし、他の上できれいに少しタイムアウトを実行する関数を記述しようとすることでそうやって期待通りに終了しません関数呼び出し。しかし、私は理解できない問題に遭遇しました。マルチプロセッシング上のPythonのドキュメントによると

(終了)は、「優れた作品を完了せずに、すぐにワーカープロセスを停止します。」

しかし、これをテストすると、pool.terminate()は、ワーカープロセスが終了するのを待たずに終了するようです。私はこのコードを実行したときに

だから:

import multiprocessing.pool 
from time import sleep 

def timeout(seconds, function, *args, **kwargs): 

    pool = multiprocessing.pool.ThreadPool(processes = 1) 
    result = pool.apply_async(function, args, kwargs) 

    try: result.get(seconds) 
    except multiprocessing.context.TimeoutError: 
     print("Process timed out") 
     pool.terminate() 
     pool.join() 
     print("Pool terminated") 
    finally: 
     pool.close() 

def worker(): 
    for n in range(5): 
     sleep(1) 
     print(n+1) 
    print("Process succeeded") 

timeout(2.5, worker) 

を私は結果はこのことを期待:

1 
2 
Process timed out 
Pool terminated 

しかし、その代わりに、私はこれを取得:

1 
2 
Process timed out 
3 
4 
5 
Process succeeded 
Pool terminated 

私はresult.getことを知っています"Process timed out"というメッセージが正常に印刷されたため、TimeoutErrorが発生しました。そして私は同じ理由でpool.terminate()が呼ばれたことを知っています。ただ何もしていないようです。

ここに私が理解していない何かがあるように感じます。誰かが私を助けてくれますか?

+0

私はこれがWindowsの問題だと思っています - Linuxではほぼ確実に信号を送信していますWindows 7 AFAIKでは利用できません。 –

答えて

1

理由はわかりませんが、この問題は、pool.join()コールが原因であるように見えますが、ワーカープロセスは前のterminate()コールで終了しているため、実際には必要ありません。

import multiprocessing.pool 
from time import sleep 

def timeout(seconds, function, *args, **kwargs): 
    pool = multiprocessing.pool.ThreadPool(processes=1) 
    result = pool.apply_async(function, args, kwargs) 
    try: 
     result.get(timeout=seconds) 
    except multiprocessing.TimeoutError: 
     print("Process timed out") 
    pool.terminate() 
# pool.join() # Don't need this, all worker threads have been stopped. 
    print("Pool terminated") 

def worker(): 
    for n in range(5): 
     sleep(1) 
     print(n+1) 
    print("Process succeeded") 

timeout(2.5, worker) 

出力:かかわらず

1 
2 
Process timed out 
Pool terminated 

、バージョン3.3以降、Poolオブジェクトは、それが使われているときPool.terminate()が自動的に呼び出されることを意味しますコンテキスト管理プロトコルをサポートすることに注意してください - ので、機能はもっとだったかもしれません簡潔にこのように書かれています:

def timeout(seconds, function, *args, **kwargs): 
    with multiprocessing.pool.ThreadPool(processes=1) as pool: 
     result = pool.apply_async(function, args, kwargs) 
     try: 
      result.get(timeout=seconds) 
     except multiprocessing.TimeoutError: 
      print("Process timed out") 
    print("Pool terminated") 
+0

ありがとう!これは本当に役に立つ答えです。私はあなたがjoin()を使ってterminate()を続けるべきだと思っていましたが、私はそれが二枚目だと思います。私は、通常、Pythonスクリプトを実行しているときにこれが動作しますが、IDLEで実行すると動作しないことに気付きました。それを修正する方法はありますか?それともあまりにも多くを求めているのですか? – user2320886

+0

ようこそ。申し訳ありませんが、実際にIDLEで動作しない理由は何もありません(特に私は自分自身を使用しないため)。正確にどのように動作しませんか? – martineau

+0

実験として、 'timeout(2.5、worker)'を 'if __name__ == '__main __':'(またはそれに相当するIDLEに相当するもの)を前置して条件付きにしてみてください。 – martineau

関連する問題