【问题标题】:Where is proper place to install AsyncIOMainLoop() for Tornado application为 Tornado 应用程序安装 AsyncIOMainLoop() 的合适位置在哪里
【发布时间】:2018-02-09 07:37:21
【问题描述】:

所以我怀疑我看到的两种安装 AsyncIOMainLoop() 的方法中哪一种更正确。哪个更合适?

1st 当 AsyncIOMainLoop() 安装在 make_app() 代码中时:

class MainHandler(tornado.web.RequestHandler):
    async def get(self, *args, **kwargs):
        return self.write("OK")

    async def post(self, *args, **kwargs):
        return self.write("OK")

def make_app():
    tornado.platform.asyncio.AsyncIOMainLoop().install()
    return tornado.web.Application([(r"/", MainHandler),],
                                   debug=False)

def start_app():
    app = make_app()
    app.listen(8888)
    asyncio.get_event_loop().run_forever()


if __name__ == "__main__":
    start_app()

第二次在 start_app() 代码中安装 AsyncIOMainLoop() 时:

class MainHandler(tornado.web.RequestHandler):
    async def get(self, *args, **kwargs):
        return self.write("OK")

    async def post(self, *args, **kwargs):
        return self.write("OK")

def make_app():
    return tornado.web.Application([(r"/", MainHandler),],
                                   debug=False)

def start_app():
    tornado.platform.asyncio.AsyncIOMainLoop().install()
    app = make_app()
    app.listen(8888)
    asyncio.get_event_loop().run_forever()


if __name__ == "__main__":
    start_app()

您认为这两种方法中哪一种更合适?

对于第一个,我在一个 AsyncHTTPTestCase 套件中运行超过 2 个测试时遇到了问题,错误如下:

Traceback (most recent call last):
  File "/home/kamyanskiy/.local/share/virtualenvs/test-0zFWLpVX/lib/python3.6/site-packages/tornado/testing.py", line 380, in setUp
    self._app = self.get_app()
  File "/home/kamyanskiy/work/test/test_app.py", line 10, in get_app
    return web1.make_app()
  File "/home/kamyanskiy/work/test/web1.py", line 74, in make_app
    tornado.platform.asyncio.AsyncIOMainLoop().install()
  File "/home/kamyanskiy/.local/share/virtualenvs/test-0zFWLpVX/lib/python3.6/site-packages/tornado/ioloop.py", line 181, in install
    assert not IOLoop.initialized()
AssertionError

对于第二个,当 AsyncIOMainLoop() 安装在 start_app() 代码中时 - 测试运行正常,但在这里我怀疑在测试期间 AsyncIOMainLoop() 没有使用。

测试看起来像:

from tornado.testing import AsyncHTTPTestCase
import web1

class TestTornadoAppBase(AsyncHTTPTestCase):

    def get_app(self):
        return web1.make_app()

    # I have to uncomment this for 1st code example 
    # def tearDown(self):
    #    self.io_loop.clear_instance()  
    #    super().tearDown()

class TestGET(TestTornadoAppBase):
    def test_root_get_method(self):
        response = self.fetch("/")
        self.assertEqual(response.code, 200)
        self.assertEqual(response.body.decode(), 'OK')

    def test_root_post_method(self):
        response = self.fetch("/", method="POST", body='{"k": "v"}')
        self.assertEqual(response.code, 200)
        self.assertEqual(response.body.decode(), 'OK')

那么选择在哪里初始化 AsyncIOMainLoop() 的真正方法是什么?

【问题讨论】:

  • 在您的示例中,我看不到您需要安装 AsyncIOMainLoop 的任何要求。
  • @Sraw 你是对的,但这是一个简单的例子,就像我必须用测试覆盖的项目的“伪”代码一样,并且 AsyncIOMainLoop 用于使用需要 asyncio 循环的 aio 库,所以Tornado 应用程序必须使用 AsyncIOMainLoop 运行。使用 tornado 的原生 ioloop 似乎减轻了 100% 的痛苦。
  • 所以在这种情况下,我认为你需要覆盖get_new_ioloop。参考:tornadoweb.org/en/stable/…
  • @Sraw 谢谢你,好建议。所以使用 get_new_ioloop() 我总是在测试中使用 AsyncIOMainLoop,很好。

标签: python unit-testing tornado


【解决方案1】:

肯定是documentation 所说的第二个例子:

from tornado.platform.asyncio import AsyncIOMainLoop
import asyncio
AsyncIOMainLoop().install()
asyncio.get_event_loop().run_forever()

关键是必须先安装AsyncIOMainLoop,然后再告诉asyncio 运行循环。

【讨论】:

  • 谢谢你,我也越来越倾向于选择第二种方式,但你认为在测试期间没有安装 AsyncIOMainLoop 而是使用原生 IOLoop 吗?
  • 您是否尝试在您的setUp() 类的setUp() 方法中安装AsyncIOMainLoop
  • 实际上不,我覆盖了 AsyncHTTPTestCase 的 def get_new_ioloop(self): 并在那里返回 AsyncIOMainLoop。 example here
猜你喜欢
  • 1970-01-01
  • 2012-09-29
  • 2012-05-18
  • 1970-01-01
  • 2012-05-06
  • 2023-03-15
  • 2018-05-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多