Уведомления

Группа в Telegram: @pythonsu

#1 Июнь 16, 2009 16:14:22

van-gog
От:
Зарегистрирован: 2008-04-19
Сообщения: 13
Репутация: +  0  -
Профиль   Отправить e-mail  

twisted.web2 и долгие вычисления

В общем есть задача - написать сервер, при обращении к которому выбиралась статистика из базы и возвращалась пользователю.
Код:
Запуск сервера

from twisted.application import internet, service, strports
from twisted.web2 import server, channel
from testclacc import TestClass

from twisted.internet import reactor


application = service.Application("tizerserver")

port = 8080
site = server.Site(TizerWeb())
s = strports.service('tcp:' + str(port), channel.HTTPFactory(site))
s.setServiceParent(application)

reactor.run()
Обработка запросов
from twisted.web2 import server, http, resource
from twisted.web2 import http_headers, responsecode
from twisted.web2 import iweb
from twisted.internet import reactor, threads, defer
from longcalculations import LongCalc

def _httpResponse(code,text):
return http.Response(
code,
{'content-type': http_headers.MimeType('text', 'html')},
"""<html><body>%s</body></html>""" % (text))

class TestClass(resource.PostableResource):
def locateChild(self, request, segments):
return (self, server.StopTraversal)

def render(self, ctx):
request = iweb.IRequest(ctx)

# FIX remote address
try:
request.remoteAddr.host = request.headers.getRawHeaders('X-Real-Ip')[0]
except:
pass
request.referer = 'None'
request.useragent = 'NoUA'
try:
request.referer = request.headers.getRawHeaders('referer')[0]
request.useragent = request.headers.getRawHeaders('user-agent')[0]
except:
pass
# dispatch request
request.postpath = [p for p in request.postpath if p]
if len(request.postpath) < 2:
return _httpResponse(responsecode.OK, 'Great Universe')
else:
action = request.postpath.pop(0)
id_par = request.postpath.pop(0)
render = 'fl_' + action
if hasattr(self, render):
return getattr(self, render)(request, id_par)
else:
return _httpResponse(response.NOT_FOUND,
'Action Not Found %s' % (render))

def fl_test(self, request, parameter):
##################
# Здесь нужно вызвать функцию LongCalc().doLongCalc()
##########################
return _httpResponse(responsecode.OK, data_from_long_calc)
Вопрос: как реализовать вызов функции LongCalc().doLongCalc() в потоке так, чтобы ее результат вывелся пользователю?

Помогите плз.



Офлайн

#2 Июнь 16, 2009 17:42:51

Андрей Светлов
От:
Зарегистрирован: 2007-05-15
Сообщения: 3137
Репутация: +  14  -
Профиль   Адрес электронной почты  

twisted.web2 и долгие вычисления

нужно возвращать не http.Response а deferred, полученный из reactor.callInThread
на него навесть свои callback/errback. Где-то так.
Основы работы с deferred неплохо изложены в документации.



Офлайн

#3 Июнь 17, 2009 00:13:18

bw
От:
Зарегистрирован: 2007-09-26
Сообщения: 938
Репутация: +  20  -
Профиль   Адрес электронной почты  

twisted.web2 и долгие вычисления

callInThread не возвращает Deferred, нужно использовать twisted.internet.threads.deferToThread.
Примерно так:

def render(self, ctx)
...
def cb(result):
# завернуть данные в response, например
return _httpResponse(OK, result)

def eb(reason):
# вернуть response с описанием ошибки
return Response(INTERNAL_SERVER_ERROR, stream = u'Ошибка')

return deferToThread(my_long_calc_func)\
.addCallback(cb)\
.addErrback(eb)
Я с web2 не работал, в таком контексте, так что может с Response что и напутал, но по примеру должно быть понятно, о чем речь. Но в Nevow я поступил именно так бы.

..bw



Офлайн

#4 Июнь 17, 2009 15:08:03

Андрей Светлов
От:
Зарегистрирован: 2007-05-15
Сообщения: 3137
Репутация: +  14  -
Профиль   Адрес электронной почты  

twisted.web2 и долгие вычисления

bw
Да, ошибся. Отвечал “по памяти” и поленился перепроверить.



Офлайн

#5 Июнь 17, 2009 15:37:25

van-gog
От:
Зарегистрирован: 2008-04-19
Сообщения: 13
Репутация: +  0  -
Профиль   Отправить e-mail  

twisted.web2 и долгие вычисления

Спасибо, сейчас буду пробовать



Офлайн

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version