在 RequestHandler 写入的情况下 Yield 和 Await 的不同行为(Tornado Web Framework)
Different behaviour for Yield and Await in case of RequestHandler write ( Tornado Web Framework )
我正在使用 RequestHandler 使用 Tornado Web 框架进行基于 Web 的调用。以前我使用的是支持 @gen.coroutine 和 yield 的 Tornado 版本 5.1.1。
我正在将我的 tornado 版本移动到 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(龙卷风版本 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 并且当我为 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 Documentation,根据 RequestHandler 的写入方法不支持 Future 对象。:
RequestHandler.write(chunk: Union[str, bytes, dict]) → None
问题
根据文档,没有必要为self.write添加等待。我很困惑这是否会在不添加等待的情况下使 self.write 在网络上异步?
WebSocketHandler.close() 方法相同。
write()
实际上并没有将数据写入网络。它只将数据写入内存缓冲区。这个操作很快,不需要异步。
要真正将数据发送到网络,还有另一种方法叫做 flush()
,可以是 awaited/yielded。
flush()
在需要 return 数据块或循环的情况下很有用:
while True:
self.write("some data") # writes to buffer
await self.flush() # writes to network
如果您 return 一次性获取所有数据,则不必担心调用 flush()
。当处理程序退出时,Tornado 会自动为您执行此操作。
我正在使用 RequestHandler 使用 Tornado Web 框架进行基于 Web 的调用。以前我使用的是支持 @gen.coroutine 和 yield 的 Tornado 版本 5.1.1。
我正在将我的 tornado 版本移动到 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(龙卷风版本 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 并且当我为 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 Documentation,根据 RequestHandler 的写入方法不支持 Future 对象。:
RequestHandler.write(chunk: Union[str, bytes, dict]) → None
问题
根据文档,没有必要为self.write添加等待。我很困惑这是否会在不添加等待的情况下使 self.write 在网络上异步?
WebSocketHandler.close() 方法相同。
write()
实际上并没有将数据写入网络。它只将数据写入内存缓冲区。这个操作很快,不需要异步。
要真正将数据发送到网络,还有另一种方法叫做 flush()
,可以是 awaited/yielded。
flush()
在需要 return 数据块或循环的情况下很有用:
while True:
self.write("some data") # writes to buffer
await self.flush() # writes to network
如果您 return 一次性获取所有数据,则不必担心调用 flush()
。当处理程序退出时,Tornado 会自动为您执行此操作。