在请求处理程序写入的情况下,Yield和Await的不同行为(Tornado Web框架)



我正在使用RequestHandler通过Tornado Web框架进行基于Web的调用。以前我使用的是支持@gen.coroutine和yield的Tornado Version 5.1.1。

我正在将我的龙卷风版本移动到 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()
  • 主装卸机 ( 龙卷风版本 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)
  • 主处理程序 ( 版本 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)

在装饰协程的情况下,它工作正常,但是当我使它异步等待并且当我为self.write()添加await时,我开始收到错误

错误:

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

问题

根据文档,没有必要为 self.write 添加 await。我很困惑这会在不添加等待的情况下使 self.write 在网络上异步吗?

WebSocketHandler.close() 方法也是如此。

write()实际上并没有将数据写入网络。它仅将数据写入内存缓冲区。此操作非常快,不需要异步。

为了实际将数据发送到网络,还有另一种称为flush()的方法,可以等待/生成。

flush()在必须以块或循环形式返回数据的情况下很有用:

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

如果您要一次性返回所有数据,则不必担心调用flush()。当处理程序退出时,龙卷风会自动为您执行此操作。

最新更新