I use aiohttp as a client inside tornado,but the aiohttp.Timeout raises an RuntimeError.
code example:
import asyncio
import aiohttp
import tornado.web
from tornado.platform.asyncio import AsyncIOMainLoop
class MainHandler(tornado.web.RequestHandler):
async def get(self):
with aiohttp.Timeout(1):
result = await aiohttp.get("www.github.com")
self.write(result)
def make_app():
return tornado.web.Application([
(r"/", MainHandler),
])
if __name__ == "__main__":
AsyncIOMainLoop().install()
app = make_app()
app.listen(8888)
asyncio.get_event_loop().run_forever()
the exception is:
Uncaught exception GET / (::1)
HTTPServerRequest(protocol='http', host='localhost:8888', method='GET', uri='/', version='HTTP/1.1', remote_ip='::1', headers={'Host': 'localhost:8888', 'Connection': 'keep-alive', 'If-None-Match': '"e02aa1b106d5c7c6a98def2b13005d5b84fd8dc8"', 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8', 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.102 Safari/537.36', 'Accept-Language': 'en,zh-CN;q=0.8,zh;q=0.6,ja;q=0.4,zh-TW;q=0.2', 'Upgrade-Insecure-Requests': '1', 'Accept-Encoding': 'gzip, deflate, sdch'})
Traceback (most recent call last):
File "/Users/justfly/Developer/envs/new_tornado_env/lib/python3.5/site-packages/tornado/web.py", line 1445, in _execute
result = yield result
File "/Users/justfly/Developer/envs/new_tornado_env/lib/python3.5/site-packages/tornado/gen.py", line 1008, in run
value = future.result()
File "/Users/justfly/Developer/envs/new_tornado_env/lib/python3.5/site-packages/tornado/concurrent.py", line 232, in result
raise_exc_info(self._exc_info)
File "<string>", line 3, in raise_exc_info
File "/Users/justfly/Developer/envs/new_tornado_env/lib/python3.5/site-packages/tornado/gen.py", line 282, in wrapper
yielded = next(result)
File "<string>", line 6, in _wrap_awaitable
File "test.py", line 11, in get
with aiohttp.Timeout(1):
File "/Users/justfly/Developer/envs/new_tornado_env/lib/python3.5/site-packages/aiohttp/helpers.py", line 478, in __enter__
raise RuntimeError('Timeout context manager should be used '
RuntimeError: Timeout context manager should be used inside a task
I'll start looking into this one
@asvetlov tornado doesn't update asyncio.tasks.Task._current_tasks so this context manager likely can't be made to work in tornado.
Yes, aiohttp.Timeout work only inside an asyncio task context.
aiohttp creates a task for handling web requests by server api.
Tornado uses another technique not relying on tasks.
@bdarnell I believe the issue cannot be solved but want to let you know about it's existance at least.
aiohttp.Timeout has the same implementation as asyncio.timeout but exists here because aiohttp has much shorter release cycle.
Ugh. Yeah, that's relying on asyncio implementation details and cannot be used in any application or library that hopes to be portable across coroutine runners.
To address @imjustfly's issue: Many asyncio methods assume that the whole world is asyncio, and don't work well when mixing asyncio and Tornado. The Tornado versions of these methods are generally better about this, so I'd recommend using tornado.gen.with_timeout instead:
from datetime import timedelta
from tornado.gen import with_timeout, convert_yielded
result = await with_timeout(timedelta(seconds=1),
convert_yielded(aiohttp.get('http://www.example.com')))
(The convert_yielded call is because Tornado isn't perfect about accepting asyncio coroutines either. This will go away in the next release of Tornado).
@bdarnell Got it ! Thank you.
This thread has been automatically locked since there has not been
any recent activity after it was closed. Please open a [new issue] for
related bugs.
If you feel like there's important points made in this discussion,
please include those exceprts into that [new issue].
Most helpful comment
To address @imjustfly's issue: Many asyncio methods assume that the whole world is asyncio, and don't work well when mixing asyncio and Tornado. The Tornado versions of these methods are generally better about this, so I'd recommend using tornado.gen.with_timeout instead:
(The convert_yielded call is because Tornado isn't perfect about accepting asyncio coroutines either. This will go away in the next release of Tornado).