Самый нормальный вариант - twisted! Можно взять самый простой пример echoclient/echoserver
twistedmatrix.com/documents/current/core/examples
Ну и вариант по-сложнее -
https://habrahabr.ru/post/97201/
Также немного нужно вывернуть мозг с асинхронным программироавнием и deferred.
Собственно у меня это получилось за два-три дня. Сейчас куча вещей на нем написана, могу подсказать :-)
Да хоть сервер (web) на нем поднять, к которому будут клиенты коннектиться и давать ему задания - дело 10 строк.
Да, на твистед есть и аналог торнадо -
cyclone.io
Это практически полный аналог торнадо (и по производительности), но со всеми плюшками твистед. Я его тоже активно пользую, для веб-морд своих приложений.
А вот и пример на скорую руку:
import cyclone.web
import sys
from twisted.internet import reactor, threads
from twisted.python import log
def doLongCalculation():
# .... do long calculation here ...
return 3
result = 0
def doResult(x):
global result
result = x
class StartHandler(cyclone.web.RequestHandler):
def get(self):
# run method in thread and get result as defer.Deferred
d = threads.deferToThread(doLongCalculation)
d.addCallback(doResult)
self.write("Start!")
class StatusHandler(cyclone.web.RequestHandler):
def get(self):
global result
self.write("Result = %s" % (result))
if __name__ == "__main__":
application = cyclone.web.Application([
(r"/", StatusHandler),
(r"/start", StartHandler)
])
log.startLogging(sys.stdout)
reactor.listenTCP(8888, application, interface="127.0.0.1")
reactor.run()
В глобальной переменной result, будет лежать значение после старта по обращению (я браузером пользовался)
localhost:8888/start , которое отработается в треде методом doLongCalculation, а результат будет обработан методом doResult. Ответ смотрим браузером по
localhost:8888
В общем, вариантов масса.