2017-07-17 97 views
1

新手在这里Pythonsympy。我有一个简单的问题。python多处理的语义是什么?加入超时。为什么它挂起

如果我启动一个使用多重处理的工人,并在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() 

问:是否有可能迫使工人在超时终止?有没有其他的选择来做到这一点?我在上面做错了什么?

如果不可能在连接时强制超时,那么如果worker不能加入,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() 

我还需要测试它更使确定工作进程()确实因终止而被杀害,因为我不想让僵尸工作人员在身边。

+0

你确定这个函数有一个基本积分吗? – Anis

+0

@Anis这一个没有。但这实际上并不重要。我只需要在sympy电话上设置一个超时时间。 – Nasser

回答

1

你的代码从来没有达到print“及时”的原因是因为它没有超出result=que.get()。您为p.join指定了一个超时时间,使得调用进程在指定的超时后恢复。然而que.get也是阻塞的,因此等待一个项目被放入队列中。您也可以在此处指定超时时间:que.get(timeout=...)或只需关闭屏蔽:que.get(block=False)。无论如何,如果队列中没有可用项目,则会引发queue.Empty异常。

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

+0

谢谢。我使用'que.get(block = False)'添加了更新后的代码,目前它似乎工作正常。但我不确定是否还需要检查其他事情。 – Nasser