使用多处理在web2py中停止长时间运行的操作

问题描述 投票:1回答:1

我有一个web2py应用程序,它基本上用作Python脚本的浏览器界面。这个脚本通常很快就会返回,但有时可能需要很长时间。我想为用户提供一种方法,以便在脚本执行时间过长时停止执行。

我目前正在调用这样的函数:

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是None。
  2. 即使会议是相同的,kill()也没有正确杀害孩子们。
  3. 长时间运行的函数将挂起web2py线程,因此在函数完成之前,stop()甚至没有被处理。

我考虑过不调用join()并使用AJAX稍后获取函数的结果,但是我无法将过程对象保存在session中供以后使用。管道似乎能够被腌制,但后来我遇到了无法从另一个视图访问同一会话的问题。

我该如何实现此功能?

python multithreading session web2py kill-process
1个回答
1
投票

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

您可以执行简单的Ajax轮询,以在任务完成时通知客户端(或使用websockets或SSE实现更复杂的功能)。

© www.soinside.com 2019 - 2024. All rights reserved.