Использование tornado с aiohttp (или другими библиотеками на основе asyncio)

Я хочу использовать торнадо с асинхронными библиотеками, такими как aiohttp и собственные сопрограммы python 3.5, и, похоже, это поддерживается в последней версии торнадо (4.3). Однако при использовании его в цикле событий торнадо обработчик запроса зависает на неопределенный срок. Если aiohttp не используется (т. е. без строк r = await aiohttp.get('http://google.com/') и text = await r.text() ниже), обработчик запросов работает как обычно.

Мой тестовый код выглядит следующим образом:

from tornado.ioloop import IOLoop
import tornado.web
import tornado.httpserver
import aiohttp

IOLoop.configure('tornado.platform.asyncio.AsyncIOLoop')


class MainHandler(tornado.web.RequestHandler):
    async def get(self):
        r = await aiohttp.get('http://google.com/')
        text = await r.text()
        self.write("Hello, world, text is: {}".format(text))

if __name__ == "__main__":
    app = tornado.web.Application([
        (r"/", MainHandler),
    ])
    server = tornado.httpserver.HTTPServer(app)
    server.bind(8888, '127.0.0.1')
    server.start()
    IOLoop.current().start()

person Leonth    schedule 13.01.2016    source источник


Ответы (2)


Согласно документам, вы делаете это почти правильно. Вы должны создать/инициировать ioloop Tornado с соответствующим asyncio, так как aiohttp работает на asyncio.

from tornado.ioloop import IOLoop
import tornado.web
import tornado.httpserver
import aiohttp
from tornado.platform.asyncio import AsyncIOMainLoop
import asyncio

class MainHandler(tornado.web.RequestHandler):
    async def get(self):
        r = await aiohttp.get('http://google.com/')
        text = await r.text()
        self.write("Hello, world, text is: {}".format(text))

if __name__ == "__main__":
    AsyncIOMainLoop().install()
    app = tornado.web.Application([
        (r"/", MainHandler),
    ])
    server = tornado.httpserver.HTTPServer(app)
    server.bind(1234, '127.0.0.1')
    server.start()
    asyncio.get_event_loop().run_forever()

Причина, по которой ваш код зависает, заключается в том, что ioloop asyncio на самом деле не работает, только один Tornado, поэтому await ожидает бесконечно.

person kwarunek    schedule 13.01.2016
comment
Спасибо, например, но последняя строка немного неверна. Вызов start() вызывает AttributeError при завершении, поэтому вы должны запустить цикл только с помощью: asyncio.get_event_loop().run_forever() - person Liubov; 27.06.2018

Начиная с Tornado 5, большинство его асинхронных функций, классов и декораторов, включая IOLoop, не только совместимы со стандартным Python asyncio, но и являются псевдонимами своим аналогам при работе на Python 3.5+.

Это означает, что когда вы используете вещи Tornado, такие как IOLoop(), @gen.coroutine и тому подобное, за кулисами Tornado использует эквивалентные функции и классы в asyncio.

Таким образом, вы можете использовать IOLoop.current().start(), и вы получите ilooop asyncio.

person MestreLion    schedule 27.02.2019