python-trio / trio-asyncio

a re-implementation of the asyncio mainloop on top of Trio
Other
188 stars 37 forks source link

aiohttp example from their README does not work #51

Closed lordi closed 5 years ago

lordi commented 5 years ago

I took the example from aiohttp README and added trio_asyncio magic:

import aiohttp
import trio
import trio_asyncio
import asyncio

async def fetch(session, url):
    async with session.get(url) as response:
        return await response.text()

async def main():
    async with aiohttp.ClientSession() as session:
        html = await fetch(session, 'http://python.org')
        print(len(html))

async def async_main_wrapper(*args):
    async with trio_asyncio.open_loop() as loop:
        assert loop == asyncio.get_event_loop()
        await main()

trio.run(async_main_wrapper)

This results in:

Traceback (most recent call last):
  File "test.py", line 20, in <module>
    trio.run(async_main_wrapper)
  File "venv/lib/python3.7/site-packages/trio/_core/_run.py", line 1337, in run
    raise runner.main_task_outcome.error
  File "test.py", line 18, in async_main_wrapper
    await main()
  File "test.py", line 12, in main
    html = await fetch(session, 'http://python.org')
  File "test.py", line 7, in fetch
    async with session.get(url) as response:
  File "venv/lib/python3.7/site-packages/aiohttp/client.py", line 1005, in __aenter__
    self._resp = await self._coro
  File "venv/lib/python3.7/site-packages/aiohttp/client.py", line 417, in _request
    with timer:
  File "venv/lib/python3.7/site-packages/aiohttp/helpers.py", line 568, in __enter__
    raise RuntimeError('Timeout context manager should be used '
RuntimeError: Timeout context manager should be used inside a task

What causes this error? What would be a better way to call aiohttp from trio?

smurfix commented 5 years ago

Opening an asyncio loop is just the first step. You didn't actually switch to that asyncio context.

You can fix this by decorating your main with @aio_as_trio, or by calling aio_as_trio(fetch)(session, …). (Not both!)

However, aiohttp is a bit fiddly in that it expects to be in asyncio context for some sync operations, thus I'd definitely recommend the former method.

lordi commented 5 years ago

Ok, this works. Thank you. Maybe the docs can be improved with regard to that. It was not clear to me.