AioHTTPTestCase引发RuntimeError:线程'MainThread'中没有当前事件循环

时间:2018-02-03 17:36:27

标签: python python-3.5 python-asyncio python-unittest aiohttp

我为aiohttp.Applcation定义了unittestApplication,如下所示。

# main.py

import asyncio
from aiohttp import web

async def background_task():
    await asyncio.sleep(5)

async def start_up_test(app):
    app.loop.create_task(background_task())

def get_application(bg_tasks=[]):
    app = web.Application()
    app.on_startup.append(start_up_test)
    return app
# main_test.py

import main
from aiohttp import test_utils

class TestMain(test_utils.AioHTTPTestCase):

    async def get_application(self):
        return main.get_application()

    @test_utils.unittest_run_loop
    async def test_main(self):
        pass
$ python -m unittest main_test
Task exception was never retrieved
future: <Task finished coro=<background_task() done, defined at /home/sangmin/workspace/main.py:78> exception=RuntimeError("There is no current event loop in thread 'MainThread'.",)>
Traceback (most recent call last):
  File "/usr/lib/python3.5/asyncio/tasks.py", line 239, in _step
    result = coro.send(None)
  File "/home/sangmin/workspace/main.py", line 79, in background_task
    await asyncio.sleep(5)
  File "/usr/lib/python3.5/asyncio/tasks.py", line 510, in sleep
    loop = events.get_event_loop()
  File "/usr/lib/python3.5/asyncio/events.py", line 632, in get_event_loop
    return get_event_loop_policy().get_event_loop()
  File "/usr/lib/python3.5/asyncio/events.py", line 578, in get_event_loop
    % threading.current_thread().name)
RuntimeError: There is no current event loop in thread 'MainThread'.
.
----------------------------------------------------------------------
Ran 1 test in 0.021s

OK

TestCase引发了一个例外There is no current event loop in thread 'MainThread'

然后我发现aiohttp DOC在单元测试时提及main loop

  

某些库如motor,aioes和其他库依赖于asyncio循环来执行代码。运行正常程序时,这些库通过执行asyncio.get_event_loop来选择主事件循环。

     

测试期间的问题是没有分配主循环,因为创建了每个测试的独立循环而没有将其指定为主循环。

根据DOC,异常的原因是因为在asyncio.get_event_loop上没有分配main loop时调用unittest,我可以看到await asyncio.sleep(1)访问{{1通过调用main loop上面的get_event_loop

然后,我很困惑,因为我认为Trace应该由Application服务的test loop运行,并且AioHTTPTestCase中的所有协同程序也应该使用相同的Application loop不是main loop

我错过了什么以及如何解决?

- - - - 修改 -----

跟踪aiohttp源代码,我可以简化问题。

import asyncio

async def test():
    await asyncio.sleep(1)

if __name__ == '__main__':
    # setUp method of AioHTTPTestCase clear main loop and return new loop. 
    asyncio.set_event_loop(None)
    loop = asyncio.new_event_loop()

    # unittest_run_loop decorator run coroutine over the new loop.
    loop.run_until_complete(test())

    # This simple code also raises the same exception.

这种行为对asyncio来说是正常的。

0 个答案:

没有答案