2016-04-15 118 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它幾乎肯定發送信號,wh ich在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

作爲一個試驗,試着通過在if前加上'if__name__ =='__main __':'(或者任何相當於IDLE的IDLE)來使'timeout(2.5,worker)'有條件。 – martineau