Rozważmy ten krótki fragment:Jak korzystać z asynchronizmu w stylu Python 3.5 i czekać w Tornado na strony internetowe?
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
korzysta z pre-3.5 sposób robienia funkcje asynchroniczne w Tornado, i to działa dobrze. Jednakże, as the documentation states, korzystne jest użycie PEP 0492 dla czytelności i szybkości.
Dokumentacja mówi:
Wystarczy użyć
async def foo()
zamiast definicji funkcji z@gen.coroutine
dekoratora iawait
zamiastyield
.
Tak więc napisałem NewWsHandler
. Jednak podczas wysyłania komunikatu websocket wywołuje on ostrzeżenie:
/usr/lib/python3.5/site-packages/tornado/websocket.py:417: RuntimeWarning: coroutine 'on_message' was never awaited callback(*args, **kwargs)
Naprawdę nie wiem jak (prawidłowo) to naprawić. Próbowałem go udekorować w tornado.web.asynchronous
, ale to zakłada, że jest to HTTP verb method. Więc po przesłonić finish()
(WebSockets nie wolno tego robić), wydaje się być rodzajem pracy:
class NewWsHandler(tornado.websocket.WebSocketHandler):
def finish(self):
pass
@tornado.web.asynchronous
async def on_message(self, message):
await self.write_message("echo " + message)
Ale to wciąż wygląda hackerish, i wydaje się być sprzeczne z dokumentacją. Jaki jest właściwy sposób na zrobienie tego?
Uwaga: Używam Python 3.5.1 i Tornado 4.3.
Czy istnieje sposób, w jaki mógłbym wykonać zapytanie do bazy danych (asynchronicznie) w odpowiedzi na komunikat websocket? Coś jak 'result = czekaj na zapytanie (...)'? Nie mogę znaleźć właściwego sposobu na zrobienie tego. (Oprócz "hacków" w moim pytaniu). – evertheylen
Po utworzeniu oddzielnego wywołania zwrotnego możesz zrobić, co chcesz. Trzeba tylko zachować ostrożność przy obsłudze wyjątków, ponieważ każdy zgłoszony tutaj wyjątek nie przejdzie przez 'on_message' i nie wpłynie na połączenie websocket. Należy również pamiętać, że inna wiadomość może nadejść przed zakończeniem poprzedniej; Aby tego uniknąć, możesz odrodzić wywołanie zwrotne w 'on_open()' i komunikować się z nim za pomocą kolejki. –
Dzięki! Teraz wszystko jest jasne. – evertheylen