Как дождаться вызова request.finish() в Python /Tornado

#python #tornado

#python #tornado

Вопрос:

В моем файле python у меня есть два класса обработчиков: MainHandler (tornado.web.RequestHandler) и WebSocketHandler (tornado.web.WebSocketHandler). В классе MainHandler я выполняю следующий код в методе get:

 class MainHandler(tornado.web.RequestHandler):
   #some code
   def get(self):
      #some code
      mainHandler_dict[chan] = self
      await self.finish() #line of code that would do the waiting somehow
  

Итак, я сохраняю запрос в глобальном словаре, чтобы я мог вызывать request.write() и request.finish() в on_message методе класса WebSocketHandler:

 class WebSocketHandler(tornado.websocket.WebSocketHandler):
   def on_message(self, message):
      #some code 
      request.write(body)
      request.finish()
  

Я получаю переменную «request» из глобального словаря и пытаюсь вызвать write(), но возникает следующая ошибка: RuntimeError: Cannot write() after finish()

Я думаю, finish() что он автоматически вызывается после завершения метода get в классе MainHandler. Итак, есть ли способ для RequestHandler продолжать «ждать», пока я не вызываю request.finish() где-нибудь через файл?

Комментарии:

1. Ну, вы вызываете finish очень явно, а затем ждете возвращаемого значения.

2. Но проблема в том, что когда я пытаюсь записать в request.write(body) , я думаю, что обработчик уже вызвал finish() себя. Моя строка request.finish() никогда не выполняется.

3.Нет, вы вызываете finish здесь: await self.finish() . Вы вызываете это. На этом запрос завершается.

4. Если я не выполняю эту строку, я все равно получаю ту же ошибку. Эта строка — моя попытка дождаться, пока она будет вызвана где-то еще. Я думаю, это не работает таким образом.

5. Вам нужно не допустить завершения функции, await добавив что-то, что не позволит ей завершиться, пока она не получит значение. Я опубликовал решение ниже.

Ответ №1:

Вероятно, вам следует справиться с этим наоборот; не сохраняйте «запрос», постарайтесь каким-то образом сохранить его и записать в него из другого места, а скорее позвольте обработчику запроса дождаться, пока значение, которое вам нужно, станет доступным. Например.:

 class MainHandler(RequestHandler):
    async def get(self):
        value = await magic()
        self.write(value)
  

Теперь, как обрабатывать « magic » часть, немного зависит от того, откуда берется это значение и что в вашем распоряжении, но давайте проиллюстрируем простым Future :

 async def get(self):
    futures[chan] = asyncio.Future()
    value = await futures[chan]
    self.write(value)
  

И в других местах:

 futures[chan].set_result(42)