Рассмотрим этот короткий фрагмент:
import tornado
import tornado.websocket
import tornado.ioloop
import tornado.gen
import tornado.web
class NewWsHandler(tornado.websocket.WebSocketHandler):
async def on_message(self, message):
await self.write_message("echo " + message)
class OldWsHandler(tornado.websocket.WebSocketHandler):
@tornado.gen.coroutine
def on_message(self, message):
yield self.write_message("echo " + message)
app = tornado.web.Application([(r'/', OldWsHandler)])
app.listen(8080)
tornado.ioloop.IOLoop.current().start()
OldWsHandler
использует pre-3.5 способ делать асинхронные функции в Tornado, и он отлично работает. Однако как указано в документации, рекомендуется использовать PEP 0492 для удобства чтения и скорости.
В документации написано:
Просто используйте
async def foo()
вместо определения функции с декоратором@gen.coroutine
иawait
вместоyield
.
Итак, я написал NewWsHandler
. Однако при отправке сообщения websocket возникает предупреждение:
/usr/lib/python3.5/site-packages/tornado/websocket.py:417: RuntimeWarning: coroutine 'on_message' was never awaited callback(*args, **kwargs)
Я действительно не знаю, как (правильно) исправить это. Я попытался украсить его в tornado.web.asynchronous
, но это предполагает метод HTTP-глагола. Поэтому после того, как я переопределяю finish()
(websockets не разрешено делать это), похоже, что это работает:
class NewWsHandler(tornado.websocket.WebSocketHandler):
def finish(self):
pass
@tornado.web.asynchronous
async def on_message(self, message):
await self.write_message("echo " + message)
Но это все еще выглядит хакерским и, кажется, противоречит документации. Каков правильный способ сделать это?
Примечание. Я использую Python 3.5.1 и Tornado 4.3.