Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

RuntimeError: This event loop is already running in python

I think I'm getting this error because my code calls asyncio.get_event_loop().run_until_complete(foo()) twice. Once from foo() and second time from function called by foo(). My question is then: why should this be a problem? Why should I even care that this loop is running?


There was an edit made to this question which, I think, obscured it (some people prefer to follow rules without understanding them, thus an "illegal" word was removed from the title). Unfortunately, this creates confusion.

I'm not surprised by the fact that the error is raised. I can trace it back to the asyncio source and see that the authors of this library wanted to do it this way, there's no mystery there. The puzzling part is in the reason the authors of the library decided it's illegal to ask from event loop to run some function to completion when the loop is already running.

We can reduce the problem to just two such calls, and through case analysis we will see that these are the three possibilities:

  1. Neither of both functions ever terminates.
  2. One of the functions eventually terminates.
  3. Both functions eventually terminate.

Now, is there any sane behavior which would address all three cases? To me, it is obvious that there is, or, perhaps are multiple sane behaviors possible here. For example:

  1. Nothing special, the execution of both functions is interleaved, and they keep running forever, just as expected.
  2. The loop doesn't return control to the code following the first instance of run_until_complete() until second function completes (thus no code after run_until_complete() will be executed.
  3. After the last function terminates, the loop returns control to the first code object which invoked run_until_complete ignoring all other invocation sites.

Now, I can understand that this behavior may not be something that everyone would want. But, since this library decided to give programmers control over starting / stopping the event loop, it should also meet the consequences of such decisions. Making it an error to start the same loop multiple times precludes library code from ever doing this, which reduces the quality and usefulness of libraries utilizing asyncio (which is indeed the case with, for example, aiohttp).

like image 765
wvxvw Avatar asked Oct 19 '17 09:10

wvxvw


People also ask

What is the event loop in Python?

The event loop is the core of every asyncio application. Event loops run asynchronous tasks and callbacks, perform network IO operations, and run subprocesses. Application developers should typically use the high-level asyncio functions, such as asyncio.

How do I use async await in Python?

An async function uses the await keyword to denote a coroutine. When using the await keyword, coroutines release the flow of control back to the event loop. To run a coroutine, we need to schedule it on the event loop. After scheduling, coroutines are wrapped in Tasks as a Future object.

What is Nest_asyncio?

nest-asyncio is a tool in the PyPI Packages category of a tech stack. nest-asyncio is an open source tool with 424 GitHub stars and 34 GitHub forks.

What is Asyncio Ensure_future?

ensure_future is a method to create Task from coroutine . It creates tasks in different ways based on argument (including using of create_task for coroutines and future-like objects). create_task is an abstract method of AbstractEventLoop .


2 Answers

I got the issue resolved by using the nest_async

pip install nest-asyncio 

and adding below lines in my file.

import nest_asyncio nest_asyncio.apply() __import__('IPython').embed() 
like image 141
Ovidiu Ionut Avatar answered Oct 07 '22 15:10

Ovidiu Ionut


Event loop running - is an entry point of your async program. It manages running of all coroutines, tasks, callbacks. Running loop while it's running makes no sense: in some sort it's like trying to run job executor from same already running job executor.

Since you have this question, I guess you may misunderstand a way how asyncio works. Please, read this article - it's not big and gives a good introduction.

Upd:

There's absolutely no problem in adding multiple things to be ran by event loop while this loop is already running. You can do it just by awaiting for it:

await coro()  # add coro() to be run by event loop blocking flow here until coro() is finished 

or creating a task:

# python 3.7+ asyncio.create_task(coro())  # add coro() to be run by event loop without blocking flow here  # This works in all Python versions but is less readable asyncio.ensure_future(coro()) 

As you can see you don't need call event loop's methods to make something being ran by it.

Event loop's method such as run_forever or run_until_complete — are just a ways to start event loop in general.

run_until_complete(foo()) means: "add foo() to be ran by event loop and run event loop itself until foo() isn't done".

like image 41
Mikhail Gerasimov Avatar answered Oct 07 '22 14:10

Mikhail Gerasimov