У меня есть приложение web2py, которое в основном служит интерфейсом браузера для скрипта Python. Этот скрипт обычно возвращается довольно быстро, но иногда может занять много времени. Я хочу предоставить пользователю возможность остановить выполнение скрипта, если он занимает слишком много времени.Остановить длительное действие в 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
Я столкнулся несколько основных проблем, связанных с этим.
- Сессия в
stop()
не всегда была такой же, как сессии вmyView()
, поэтомуsession.events
не было. - Даже когда сессия была такой же,
kill()
не убивал детей. - Долгосрочная функция зависает потоком web2py, поэтому
stop()
даже не обрабатывался до завершения функции.
Я считал не называя join()
и использованием AJAX, чтобы забрать результат функции в более позднее время, но я не был в состоянии сохранить объект процесса в session
для последующего использования. Казалось, что труба может быть маринована, но тогда у меня возникла проблема с невозможностью получить доступ к той же сессии из другого представления.
Как я могу реализовать эту функцию?
Не могли бы вы рассказать о своем ответе? Некоторые конкретные вещи, на которые стоит ответить: запускает ли планировщик сразу же из сценария? Как получить результат задания? Как принудительно остановить задачу? Как бы то ни было, это не полностью отвечает на вопрос. – Scimonster
Я обновил ответ, чтобы ответить на ваш последний вопрос. Ваши первые два вопроса рассматриваются в связанной документации. Поскольку они связаны с общей функциональностью планировщика и не являются частью вашего первоначального вопроса, я не буду обновлять ответ, но я вкратце упомянул, что по умолчанию новые задачи ставятся в очередь сразу (и вы можете заставить работника немедленно проверить очередь, установив 'instant = True'), а метод' scheduler.task_status() 'используется для получения результатов. – Anthony