considerare questo breve frammento:Come usare Python 3.5 in stile async e attendere in Tornado per websockets?
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
utilizza il modo di pre-3.5 di fare funzioni asincrone in Tornado, e funziona benissimo. Tuttavia, as the documentation states, è preferibile utilizzare PEP 0492 per la leggibilità e la velocità.
La documentazione dice:
sufficiente utilizzare
async def foo()
al posto di una definizione di funzione con la@gen.coroutine
decoratrice, eawait
al posto diyield
.
Così ho scritto NewWsHandler
. Tuttavia, quando si invia un messaggio websocket, solleva un avvertimento:
/usr/lib/python3.5/site-packages/tornado/websocket.py:417: RuntimeWarning: coroutine 'on_message' was never awaited callback(*args, **kwargs)
Io in realtà non so come (correttamente) risolvere il problema. Ho provato a decorarlo in tornado.web.asynchronous
, ma questo presuppone un HTTP verb method. Così, dopo sovrascrivo finish()
(WebSockets non sono autorizzati a farlo), sembra essere tipo di lavorazione:
class NewWsHandler(tornado.websocket.WebSocketHandler):
def finish(self):
pass
@tornado.web.asynchronous
async def on_message(self, message):
await self.write_message("echo " + message)
Ma questo sembra ancora hackerish, e sembra essere in contraddizione con la documentazione. Qual è il modo giusto per farlo?
Nota: sto usando Python 3.5.1 e Tornado 4.3.
C'è un modo per interrogare un database (in modo asincrono) in risposta a un messaggio websocket? Qualcosa come 'result = await query (...)'? Non riesco a trovare un buon modo per farlo. (A parte gli "hack" nella mia domanda). – evertheylen
Una volta generato un callback separato puoi fare quello che vuoi. Dovrai solo fare attenzione con la gestione delle eccezioni poiché qualsiasi eccezione qui sollevata non passerà attraverso 'on_message' e influenzerà la connessione websocket. Ricorda inoltre che potrebbe entrare un altro messaggio prima che sia terminato il precedente; per evitare che tu possa voler generare una richiamata in 'on_open()' e comunicare con essa usando una coda. –
Grazie! Adesso è tutto chiaro. – evertheylen