Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Error with async vs non async design #915

Open
ncilfone opened this issue Mar 20, 2025 · 1 comment
Open

Error with async vs non async design #915

ncilfone opened this issue Mar 20, 2025 · 1 comment
Labels
bug Something isn't working

Comments

@ncilfone
Copy link

The synchronous version just calls the async version in a loop.

Per the docs: https://futurehouse.gitbook.io/futurehouse-cookbook/paperqa#async

This can cause issues if there is already an event loop running since the 'sync' code is still calling async code under the hood.

For instance, trying to run pqa2 using Sanic (which uses uvloop under the hood to support async) and using the following code which should be 'sync'

docs.add(path=path, settings=settings)

Results in the following

File "uvloop/loop.pyx", line 1512, in uvloop.loop.Loop.run_until_complete
File "uvloop/loop.pyx", line 1505, in uvloop.loop.Loop.run_until_complete
File "uvloop/loop.pyx", line 1379, in uvloop.loop.Loop.run_forever
File "uvloop/loop.pyx", line 520, in uvloop.loop.Loop._run
RuntimeError: this event loop is already running.

TL;DR Looping async code in a sync function by simply wrapping it in run_until_complete doesn't guarantee sync behavior.

Pulling a quote from the nest_asyncio library (RIP Ewald):

"By design asyncio does not allow its event loop to be nested. This presents a practical problem: When in an environment where the event loop is already running it’s impossible to run tasks and wait for the result. Trying to do so will give the error “RuntimeError: This event loop is already running”."

Copy link

dosubot bot commented Mar 20, 2025

Hey there, @ncilfone! I'm Dosu, a bot here to help you with bug fixes, questions, and contributions. I'm here to assist you while you wait for a human maintainer.

The issue you're encountering is due to the fact that the synchronous docs.add method in PaperQA internally calls an asynchronous function using run_until_complete, which can lead to a RuntimeError if an event loop is already running, as is the case with frameworks like Sanic that use uvloop for async operations [1].

To resolve this, you should use the asynchronous version of the method, docs.aadd, directly in environments where an event loop is already active. This avoids the problem of trying to nest event loops. Here's how you can modify your code to use the async method:

import asyncio
from paperqa import Docs

async def main():
    docs = Docs()
    await docs.aadd(path=path, settings=settings)

# Ensure this is called in an environment where the event loop is managed, like within a Sanic route handler
await main()

This approach ensures that you are not attempting to run a new event loop within an existing one, thus avoiding the RuntimeError.

To continue talking to Dosu, mention @dosu.


Help Dosu learn! Give it feedback: Great Response | Irrelevant Answer | Incorrect Sources | Too Verbose | Hallucination | Bug Report | Other

@dosubot dosubot bot added the bug Something isn't working label Mar 20, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

1 participant