0
votes

I am trying to make an API call from within my service and I am running into event loop issues. Can someone help me understand what I am doing wrong?

Basically I want to make a service that does some calculations based on data pulled from a different service.

I can call this code below from a cli, but not when I start up a web app (i.e.) hitting http://127.0.0.1:8080/add

loop = asyncio.get_event_loop()
data = loop.run_until_complete(run_fetch(loop, 'http://google.com'))   

Sample code:

from aiohttp import web
import aiohttp
import asyncio

async def add(request):
    loop = asyncio.get_event_loop()
    data = loop.run_until_complete(run_fetch(loop, 'http://google.com'))
    return web.json_response(data)


async def fetch(client, url):
    async with client.get(url) as resp:
        assert resp.status == 200
        return await resp.text()


async def run_fetch(loop, url):
    async with aiohttp.ClientSession(loop=loop) as client:
        html = await fetch(client, url)
    return html

app = web.Application()
app.router.add_get('/add', add)
web.run_app(app, host='127.0.0.1', port=8080)

Exception:

Error handling request Traceback (most recent call last): File ".../aiohttp/web_protocol.py", line 417, in start resp = yield from self._request_handler(request)

File ".../aiohttp/web.py", line 289, in _handle resp = yield from handler(request)

File ".../sample.py", line 11, in add data = loop.run_until_complete(run_fetch(loop, 'http://google.com'))

File ".../python3.6/asyncio/base_events.py", line 454, in run_until_complete self.run_forever()

File ".../python3.6/asyncio/base_events.py", line 408, in run_forever raise RuntimeError('This event loop is already running')

RuntimeError: This event loop is already running

1

1 Answers

2
votes

The run_until_complete is the way to run some async code from the sync context. Under the hood it adds provided future to the given ioloop and calls run_forever then returns result or throws exception (resolved future).

Actually you need to await run_fetch(loop, 'http://google.com'), since the caller function is asynchronous.