В обработчике запросов торнадо, если мне нужно вызвать функцию foo(), которая не влияет на то, что возвращается пользователю, имеет смысл сначала вернуть результат пользователю, а затем вызвать foo(). Можно ли это легко сделать в торнадо (или в каком-нибудь стороннем пакете)?
Данные обработки Tornado в обработчике запросов после возврата
Ответы:
Нет, это не "просто" из коробки. То, что вы имеете в виду, это «выстрелил и забыл». Даже если вы используете пул потоков для обработки запроса, этот пул потоков будет принадлежать основному процессу Python, принадлежащему Tornado.
Лучшим подходом является очередь сообщений. Что-то вроде Моркови. Таким образом, предположим, что у вас есть страница, на которой пользователи могут выполнить запуск, чтобы начать генерировать ОГРОМНЫЙ отчет, вы можете запустить его в очереди сообщений, а затем завершить запрос Tornado, и с помощью некоторой магии AJAX и других трюков (вне возможностей Tornado) вы можете сидеть сложа руки и ждать, пока очередь сообщений завершит свою работу (что технически может происходить на распределенном сервере в другом физическом месте).
Это очень просто:
class Handler(tornado.web.RequestHandler):
def get(self):
self.write('response')
self.finish() # Connection is now closed
foo()
ioloop.add_callback, Tornado выполнит обратный вызов на следующей итерации IOLoop.
предупреждение о плохом совете: вы можете использовать многопроцессорность.
http://docs.python.org/library/multiprocessing.html
будьте осторожны, чтобы закрыть все соединения с базой данных (в порожденном коде) и делать все, что может сделать торнадо, когда он обычно выполняет запрос без подпроцесса. Другие ответы звучат лучше. Но вы можете это сделать. Не делай этого.