aio-libs / async-timeout

asyncio-compatible timeout class

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

RuntimeError when using two event loops

iAnanich opened this issue · comments

original question

Steps to reproduce

requirements.txt

# Python 3.5.2
aiohttp==2.1.0
async-timeout==1.2.1
chardet==3.0.4
gunicorn==19.7.1
multidict==2.1.6
yarl==0.10.3
  1. code in test.py :
import asyncio
import async_timeout
from aiohttp import web

asyncio.set_event_loop(asyncio.new_event_loop())

class A:
    async def am(self):
        with async_timeout.timeout(timeout=1):
            await asyncio.sleep(0.5)

class B:
    a = A()
    async def bm(self):
        await self.a.am()

b = B()

async def hello(request):
    await b.bm()
    return web.Response(text="Hello, world")

app = web.Application()
app.router.add_get('/', hello)
  1. run this command gunicorn test:app --worker-class aiohttp.GunicornWebWorker -b 127.0.0.1:8000

  2. make request to https://127.0.0.1:8000/ URL.

Get RuntimeError: Timeout context manager should be used inside a task error message.

question

Why in this case async_timeout class have been initialised with developer-defined event loop instead gunicorn-defined (aiohttp.GunicornWebWorker)? How can library provide more informative message to help developer understand why it isn't working?

But your example works as expected!

@asvetlov I need some time to find out why it was an error...

@asvetlov

But your example works as expected!

What do you mean "expected"?

http://127.0.0.1:8000 URL throws 500 HTTP code and prints in console RuntimeError: Timeout context manager should be used inside a task error.

Maybe you are using another package version? I have updated first post with requirements.

Your example works in new environment with versions specified in requirements.txt.
The only difference I have Python 3.5.3

Anyway, what text are you suggesting?
Current words describe situation when context manager is used from regular callback, tornado's callback or if the loop was not running.

@asvetlov I'm not fully understand what is callback. Please, help me understand.

I just doesn't understand why it have raised an error (as I understand, timeout class must call asyncio.get_event_loop at initialisation and store the result in _loop attribute to use it on __entry__ method call, and it gets initialised when A.am method called which heppens when I make request to http://127.0.0.1:8000/ URl). And my suggestiongs for the text are dependend on previous "why" question.

Because the best error message must tell me what line of code is wrong. But in the reality it isn't possible and I expect just helpfull message that points me at problem. In this case, when using 3.5.2, it isn't for me, because in my head context manager is inside coroutine method, executed inside event loop. But if it is fixed in Python 3.5.3, and everyone can use asyncio.get_event_loop, thats no problem.