Я изо всех сил пытаюсь создать такое же поведение в коде веб-службы, в котором используются отложенные объекты, и в коде, который этого не делает. Моя цель - написать декоратор, который делегирует обработку любого метода (который отделен от Twisted) пулу витых потоков, чтобы реактор не блокировался без изменения какой-либо семантики этого метода.
Когда приведенный ниже экземпляр класса echo представлен в виде веб-службы, этот код:
from twisted.web import server, resource
from twisted.internet import defer, threads
from cgi import escape
from itertools import count
class echo(resource.Resource):
isLeaf = True
def errback(self, failure): return failure
def callback1(self, request, value):
#raise ValueError # E1
lines = ['<html><body>\n',
'<p>Page view #%s in this session</p>\n' % (value,),
'</body></html>\n']
return ''.join(lines)
def callback2(self, request, encoding):
def execute(message):
#raise ValueError # E2
request.write(message.encode(encoding))
#raise ValueError # E3
request.finish()
#raise ValueError # E4
return server.NOT_DONE_YET
return execute
def render_GET(self, request):
content_type, encoding = 'text/html', 'UTF-8'
request.setHeader('Content-Type', '%s; charset=%s' %
tuple(map(str, (content_type, encoding))))
s = request.getSession()
if not hasattr(s, 'counter'):
s.counter = count(1)
d = threads.deferToThread(self.callback1, request, s.counter.next())
d.addCallback(self.callback2(request, encoding))
d.addErrback(self.errback)
#raise ValueError # E5
return server.NOT_DONE_YET
будет отображать HTML-документ в браузере, когда все операторы повышения закомментированы, и отображать хорошо отформатированную трассировку стека (что делает для меня Twisted), когда включен оператор повышения, помеченный как «E5». Это то, что я хочу. Аналогично, если я вообще не использую отложенные объекты и помещаю все поведение из callback1 и callback2 в render_GET (), исключение, возбуждаемое в любом месте render_GET, приведет к желаемой трассировке стека.
Я пытаюсь написать код, который будет незамедлительно реагировать на браузер, не вызывать утечку ресурсов в Twisted и приводить к тому, что трассировка стека браузера также будет отображаться в случаях, когда любой из операторов повышения от "E1" до "E3" включен в отложенный код - хотя, конечно, я понимаю, что сами трассировки стека будут другими. (Дело «E4» меня не особо волнует.) После прочтения документации Twisted и других вопросов на этом сайте я не уверен, как этого добиться. Я бы подумал, что добавление errback должно облегчить это, но, очевидно, нет. Должно быть что-то с отложенными объектами и стеком twisted.web, чего я не понимаю.
Влияние на ведение журнала, которое я здесь описываю, может зависеть от того, как я использовал PythonLoggingObserver для привязки Twisted logging к стандартному модулю ведения журнала.
Когда включено «E1», браузер ожидает, пока реактор не будет остановлен, после чего регистрируется исключение ValueError с трассировкой стека, и браузер получает пустой документ.
Когда включено «E2», исключение ValueError с трассировкой стека регистрируется немедленно, но браузер ждет, пока реактор не отключится, и в этот момент он получит пустой документ.
Когда включено «E3», исключение ValueError с трассировкой стека регистрируется немедленно, браузер ждет, пока реактор выключится, и в этот момент получает нужный документ.
Если включено выражение «E4», намеченный документ немедленно возвращается в браузер, и немедленно регистрируется исключение ValueError со трассировкой стека. (Есть ли вероятность утечки ресурса в этом случае?)