как правильно использовать асинхронный с торнадо - PullRequest
0 голосов
/ 28 октября 2019

в документах торнадо упоминается, что декораторы gen.coroutine относятся к более старым версиям. более новый должен использоваться с aysnc. Пока что мне не удалось преобразовать этот маленький код для Tornado 6.0.3.

import tornado.web
import tornado.websocket
import tornado.httpserver

from random import randint
from tornado import gen
from tornado.ioloop import IOLoop

from web_handlers import HandlerIndexPage
from web_handlers import HandlerWebSocket

msg = 'none'

@gen.coroutine
def generate_random_int():
    global msg
    while True:
        msg = str(randint(0, 100))
        print('generated:', msg)
        yield gen.sleep(1.0)

@gen.coroutine
def generate_message_to_sockets():
    global msg
    while True:
        print ('new messageToCon: ', msg)
        yield [con.write_message(msg) for con in HandlerWebSocket.connections]
        yield gen.sleep(1.0)


class webApplication(tornado.web.Application):
    def __init__(self):
        handlers = [
            (r'/', HandlerIndexPage),
            (r'/websocket', HandlerWebSocket)
        ]

        settings = {
            'template_path': 'templates'
        }
        tornado.web.Application.__init__(self, handlers, **settings)

if __name__ == '__main__':
    ws_app = webApplication()
    server = tornado.httpserver.HTTPServer(ws_app)
    port = 9090
    server.listen(port)
    print('websocket listening on port:'+ str(port))
    IOLoop.current().spawn_callback(generate_random_int)
    IOLoop.current().spawn_callback(generate_message_to_sockets)
    IOLoop.instance().start()

Как правильно использовать async?

1 Ответ

2 голосов
/ 29 октября 2019

В Tornado сопрограммы - это генераторы, которые можно подключить к Python2, тогда как асинхронные функции являются первоклассными гражданами в Python3. Они имеют различную семантику (например, вы можете return использовать асинхронную функцию, но не сопрограмму). Код, который вам нужно изменить, будет выглядеть следующим образом:

...

import asyncio

...

async def generate_random_int():
    global msg
    while True:
        msg = str(randint(0, 100))
        print('generated:', msg)
        await gen.sleep(1.0)

async def generate_message_to_sockets():
    global msg
    while True:
        print ('new messageToCon: ', msg)
        futures = [con.write_message(msg) for con in HandlerWebSocket.connections]
        if futures:
            await asyncio.wait(futures)
        await gen.sleep(1.0)
...

Пример, аналогичный вашему варианту использования, можно посмотреть здесь: https://www.tornadoweb.org/en/stable/ioloop.html#ioloop-objects

...