我有一个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
我遇到了一些重大问题。
stop()
的会议并不总是与myView()
的会议相同,所以session.events
是None。kill()
也没有正确杀害孩子们。stop()
甚至没有被处理。我考虑过不调用join()
并使用AJAX稍后获取函数的结果,但是我无法将过程对象保存在session
中供以后使用。管道似乎能够被腌制,但后来我遇到了无法从另一个视图访问同一会话的问题。
我该如何实现此功能?
对于长时间运行的任务,最好通过内置的scheduler排队。如果您想允许用户手动停止花费太长时间的任务,您可以使用scheduler.stop_task(ref)
方法(其中ref
是任务id
或uuid
)。或者,当您对任务进行排队时,您可以指定超时,因此如果在超时期限内未完成,它将自动停止。
您可以执行简单的Ajax轮询,以在任务完成时通知客户端(或使用websockets或SSE实现更复杂的功能)。