Различное поведение для Yield и Await в случае записи RequestHandler (Tornado Web Framework) - PullRequest
4 голосов
/ 15 апреля 2019

Я использую RequestHandler для выполнения веб-вызовов с использованием веб-фреймворка Tornado. Ранее я использовал Tornado Version 5.1.1, которая поддерживала @ gen.coroutine и yield.

Я перевожу свою версию торнадо на 6.0.2 и недавно, так как они обесценили украшенные сопрограммы, поэтому я перенес свой код на собственные сопрограммы.

Но я заметил различное поведение между украшенными сопрограммами и местными сопрограммами.

Пример :

  • main.py:
import tornado.ioloop as ioloop
import tornado.web as web
from RequestHandler import MainHandler

def main():
    application = web.Application([
        (r"/", MainHandler),
    ])
    application.listen(8080)

    ioloop.IOLoop.current().start()

if __name__ == '__main__':
    main()
  • MainHandler (Tornado Version 5.0.2)
import tornado.web
import tornado.gen

class MainHandler(tornado.web.RequestHandler):
    def initialize(self):
        self.data = "Hello World"

    @gen.coroutine
    def get(self):
        yield self.write(self.data)

    @gen.coroutine
    def post(self):
        yield self.write(self.data)

  • MainHandler (версия 6.0.2)
import tornado.web

class MainHandler(tornado.web.RequestHandler):
    def initialize(self):
        self.data = "Hello World"

    async def get(self):
        self.write(self.data)

    async def post(self):
        self.write(self.data)

В случае с Decorated Coroutines все работало нормально, но когда я сделал это async-await и когда я добавил await для self.write(), я начал получать ошибку

Ошибка:

ERROR:tornado.application:Uncaught exception GET / (::1)
HTTPServerRequest(protocol='http', host='localhost:8080', method='GET', uri='/', version='HTTP/1.1', remote_ip='::1')
Traceback (most recent call last):
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/tornado/web.py", line 1699, in _execute
    result = await result
  File "/Users/sharvin/Desktop/Personal_Projects/All_Tornado_Projects/1. Tornado_Basics/MainHandler.py", line 8, in get
    await self.write(self.data)
TypeError: object NoneType can't be used in 'await' expression
ERROR:tornado.access:500 GET / (::1) 3.45ms

Я использую self.write для записи данных в сеть.

Я проверил документацию Tornado и в соответствии с этим метод записи RequestHandler не поддерживает объект Future .:

RequestHandler.write(chunk: Union[str, bytes, dict]) → None

Вопрос

Согласно документации, нет необходимости добавлять await для self.write. Я запутался, сделает ли это self.write асинхронным в сети без добавления await?

То же самое для метода WebSocketHandler.close ().

1 Ответ

0 голосов
/ 15 апреля 2019

write() фактически не записывает данные в сеть.Он только записывает данные в буфер памяти.Эта операция очень быстрая и не должна быть асинхронной.

Для фактической отправки данных в сеть существует другой метод, называемый flush(), который можно ожидать / выдавать.

flush() полезно в тех случаях, когда вам нужно возвращать данные в виде фрагментов или в цикле:

while True:
    self.write("some data") # writes to buffer
    await self.flush() # writes to network

Если вы возвращаете все свои данные за один раз, вам не нужно беспокоиться озвонит flush().Торнадо автоматически сделает это за вас при выходе из обработчика.

...