Search code examples
pythonpython-asynciosanicsanic-openapi

Called from Sanic functions throws "asyncio.run() cannot be called from a running event loop"


I'm new to asyncio. Tried to create an async decorator with that for blocking I/O code.

def singletonAsyncMaker(func):
    async def inner(obj, ):
        loop = asyncio.get_event_loop()
        tasks = (loop.run_in_executor(None, func, i) for i in obj)
        return await asyncio.gather(*tasks)

    def main(obj):
        return asyncio.run(inner(obj))

    return main

@singletonAsyncMaker
def sleeper(obj):
    sleep(2)
    return obj

x = sleeper([8, 5, 6, 6, 4645, 63, 4, 6, 1, 64, 614, 24, 65, ])
print(x)

This worked well normally and also within normal non-async functions, but when called through a route function of a Sanic server it throws this error.

Traceback (most recent call last):
  File "/app.py", line 99, in extractImageResponse
    result = perform_textract_bytestream(images)
  File "async_experiment.py", line 51, in main
    return asyncio.run(inner(obj))
  File "env/lib/python3.8/asyncio/runners.py", line 33, in run
    raise RuntimeError(
RuntimeError: asyncio.run() cannot be called from a running event loop

@app.route("/v0/xxxxxxxxxxxxxxx", methods=['POST'])
def function_name(request):
    -----------------
    x = sleeper(list)
    -----------------
    return jsonify(json_op)

Tried adding async to sanic function_name definition and await before sleeper() call to no luck. I know that sanic works with asyncio, does that contibute to this? Any fix or work around?


Solution

  • No need to call asyncio.run inside Sanic.

    @app.route("/v0/xxxxxxxxxxxxxxx", methods=['POST'])
    async def function_name(request):
        await call_to_some_coroutine()