2016-05-18 25 views
1

我有一个基本上充当Python脚本的浏览器界面的web2py应用程序。该脚本通常很快返回,但偶尔会花费很长时间。我想为用户提供一种停止脚本执行的方法,如果时间太长。通过多处理停止web2py中的长时间操作

我目前调用这样的功能:

def myView(): # this function is called from ajax 
    session.model = myFunc() # myFunc is from a module which i have complete control over 
    return dict(model=session.model) 

myFunc,当某些选项调用,使用多,但最终还是需要很长的时间。我需要一些方法来终止函数,或者至少是线程的子进程。

我想的第一件事是在一个新的进程中运行myFunc,并推出自己的简单的事件系统来杀死它:

# in the controller 
def myView(): 
    p_conn, c_conn = multiprocessing.Pipe() 
    events = multiprocessing.Manager().dict() 
    proc = multiprocessing.Process(target=_fit, args=(options, events c_conn)) 
    proc.start() 
    sleep(0.01) 
    session.events = events 
    proc.join() 
    session.model = p_conn.recv() 
    return dict(model=session.model) 

def _fit(options, events pipe): 
    pipe.send(fitting.logistic_fit(options=options, events=events)) 
    pipe.close() 

def stop(): 
    try: 
     session.events['kill']() 
    except SystemExit: 
     pass # because it raises that error intentionally 
    return dict() 

# in the module 
def kill(): 
    print multiprocessing.active_children() 
    for p in multiprocessing.active_children(): 
     p.terminate() 
    raise SystemExit 

def myFunc(options, events): 
    events['kill'] = kill 

我跑进与这几个主要问题。

  1. stop()会议并不总是一样的会议myView(),所以session.events没有。
  2. 即使会话相同,kill()也没有正确地杀死孩子。
  3. 长时间运行的函数会挂起web2py线程,所以stop()甚至在函数完成之前都没有处理。

我认为不叫join()和使用AJAX在稍后的时间拿起函数的结果,但我没能保存过程对象session供以后使用。管道似乎可以被酸洗,但是我遇到了无法从另一个视图访问同一个会话的问题。

我该如何实现此功能?

回答

1

对于长时间运行的任务,最好通过内置的scheduler排队。如果要允许用户手动停止耗时过长的任务,可以使用scheduler.stop_task(ref)方法(其中ref是任务iduuid)。或者,当您对任务排队时,您可以指定超时时间,以便在超时时间内未完成时自动停止。

您可以通过简单的Ajax轮询在任务完成时通知客户端(或者通过websockets或SSE实现更复杂的事情)。

+0

请问您可以扩展您的答案吗?一些值得回答的具体事情:调度程序是否立即从脚本启动任务?如何获得任务的结果?如何强制停止任务?事实上,这并不能完全回答这个问题。 – Scimonster

+0

我已经更新了解决您最后一个问题的答案。您的前两个问题在链接文档中进行了介绍。由于它们涉及常规调度程序的功能并且不属于原始问题的一部分,因此我不会更新答案,但我会简要地提及,默认情况下,新任务会立即排队(并且您可以强制工作人员通过设置立即检查队列'immediate = True'),'scheduler.task_status()'方法用于检索结果。 – Anthony

相关问题