python多处理的语义是什么?加入超时。它为什么会挂起

时间:2017-07-17 11:43:57

标签: python multiprocessing sympy

新手在Pythonsympy。我有一个简单的问题。

如果我使用多处理启动一个工作者,并在join调用中给它一些小的超时,比如3秒。如果工人自己忙碌会发生什么,可能还在等待一些事情要完成?当超时到期且工作人员本身正在等待sympy时会发生什么?

我发现如果工作人员在长时间计算中调用sympy,则连接会等待工作人员,比超时时间长得多。

这是一个MWE

from multiprocessing import Process, Queue
from sympy import *
x = symbols('x')

def worker(integrand,que):
    que.put(integrate(integrand, x))

if __name__ == '__main__':       
    que = Queue()
    result = "still waiting "

    #this first call works OK since it is easy integral
    #action_process = Process(target=worker,args=(cos(x),que))

    #this one hangs inside sympy since hard integral
    p = Process(target=worker,args=(1/(x**3+cos(x)),que))

    # start the process and wait for max of 3 seconds.
    p.start()   
    p.join(timeout=3)
    result=que.get()    
    print("result from worker is " + str(result))
    p.terminate()

问题:是否可以强制工作人员在超时时终止?还有其他选择吗?我在上面做错了吗?

如果无法在加入时强制超时,那么n秒后join()的含义是什么,如果工作者不能加入?

我尝试上述操作的唯一原因是在sympy中找到一种超长计算超时的方法,因为我在Windows和定时器上并且警报在Windows上不起作用,所以我想尝试使用超时进行多处理,但它似乎没有做我想要的,因此这对我想要的东西没有任何用处。

PS。如果您运行上述操作,工作人员将在sympy内长时间停留,可能需要10分钟或更长时间,并且可能必须手动将其杀死。

以上是在Windows上。但是我也试过Linux,它也挂了。

Anacode 4.3.1,Python 3.6

更新

感谢回答提示,下面的内容现在似乎正常工作

from multiprocessing import Process, Queue
from sympy import *
x = symbols('x')

def worker(integrand,que):
    que.put(integrate(integrand, x))

if __name__ == '__main__':       
    que = Queue()
    result = "timed out "

    #this one hangs inside sympy since hard integral
    p = Process(target=worker,args=(1/(x**3+cos(x)),que))

    # start the process and wait for max of 3 seconds.
    p.start()   
    p.join(timeout=3)

    try:
       result=que.get(block=False)    
    except:
       print("timed out on que.get()")
       pass

    print("result from worker is " + str(result))
    p.terminate()

我仍然需要对它进行更多测试,以确保工作进程()确实被终止杀死,因为我不想让僵尸工作者在身边。

1 个答案:

答案 0 :(得分:1)

您的代码永远不会及时到达print“的原因是因为它没有超出result=que.get()。您为p.join指定了超时,这使得调用进程在指定的超时后恢复。但是que.get也是阻塞的,因此等待一个项目进入队列。您也可以在此处指定超时:que.get(timeout=...)或只是关闭屏蔽:que.get(block=False)。在任何情况下,如果队列中没有可用的项目,它将引发queue.Empty例外。

但是,文档包含several warnings有关终止保存(队列)共享引用的进程的信息。 Programming Guidelines似乎包含该案例的解决方案,并警告可能存在死锁(请参阅“加入使用队列的进程”)。