2016-04-15 87 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