I am using RequestHandler for making Web Based call using Tornado Web framework. Previously I was using Tornado Version 5.1.1 which supported @gen.coroutine and yield.
I am moving my tornado version to 6.0.2 and recently as they have depreciated decorated coroutines So I am moving my code to native coroutines.
But I noticed different behavior between decorated coroutines and native coroutines.
Example :
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()
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)
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)
In the case of Decorated Coroutines, it was working fine but when I made it async-await and When I added await
for self.write()
I started getting error
Error :
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
I am using self.write to write the data on the network.
I checked the Tornado Documentation and according to that RequestHandler's write method doesn't support the Future object.:
RequestHandler.write(chunk: Union[str, bytes, dict]) → None
Question
According to the documentation, it is not necessary to add await for self.write. I am confused will this make self.write asynchronous on the network without adding await?
Same for the WebSocketHandler.close() method.
write()
doesn't actually write the data to the network. It only writes the data to the memory buffer. This operation is very fast and doesn't need to be asynchronous.
To actually send the data to the network, there's another method called flush()
which can be awaited/yielded.
flush()
is useful in those cases where you've to return data in chunks or in a loop:
while True:
self.write("some data") # writes to buffer
await self.flush() # writes to network
If you're returning all your data in one go, you don't have to worry about calling flush()
. Tornado automatically does that for you when the handler exits.