erdewit / nest_asyncio

Patch asyncio to allow nested event loops
BSD 2-Clause "Simplified" License
693 stars 79 forks source link

RuntimeError: Cannot enter into task #22

Closed maartenbreddels closed 8 months ago

maartenbreddels commented 4 years ago

Hi,

thanks for this amazing package, this was for me the reason to adopt asyncio (otherwise the maintenance burden was too high).

I sometimes see this error in CI systems, and have trouble reproducing it locally:

Traceback (most recent call last):
  File "/Users/maartenbreddels/miniconda3/envs/dev/lib/python3.7/site-packages/nest_asyncio.py", line 149, in run
    ctx.run(self._callback, *self._args)
RuntimeError: Cannot enter into task <Task pending coro=<_debounced_callable.__call__.<locals>.debounced_execute.<locals>.run_async() running at /Users/maartenbreddels/src/vaex/packages/vaex-core/vaex/jupyter/utils.py:149>> while another task <Task pending coro=<InteractiveShell.run_cell_async() running at /Users/maartenbreddels/miniconda3/envs/dev/lib/python3.7/site-packages/IPython/core/interactiveshell.py:3020> cb=[IPythonKernel._cancel_on_sigint.<locals>.cancel_unless_done(<Future pendi...ernel.py:230]>)() at /Users/maartenbreddels/miniconda3/envs/dev/lib/python3.7/site-packages/ipykernel/ipkernel.py:230, IOLoop.add_future.<locals>.<lambda>() at /Users/maartenbreddels/miniconda3/envs/dev/lib/python3.7/site-packages/tornado/ioloop.py:690]> is being executed.

I wonder if you have any idea what can cause this so I can try to reproduce it and open a proper issue (or fix it).

cheers,

Maarten

avalcepina commented 4 years ago

@maartenbreddels did you find any solution to this problem? I'm using https://github.com/nats-io/stan.py and I'm basically forced to use a nested loop, but after a while (apparently randomly) I run into the same issue you are having and, after that, the loop is rendered unusable and the application cannot recover.

I can actually reproduce the error, but it is unclear what is causing it.

esbenr commented 4 years ago

I have the same issue, but with another task: Error doing job: Exception in callback <TaskWakeupMethWrapper object at 0x7f209db48fd0>(<Future finished result=True>) Traceback (most recent call last): File "/usr/local/lib/python3.7/site-packages/nest_asyncio.py", line 150, in run ctx.run(self._callback, *self._args) RuntimeError: Cannot enter into task <Task pending coro=<_async_setup_component() running at /workspaces/HomeAssistant/homeassistant/setup.py:128> wait_for=<Future finished result=True> cb=[<TaskWakeupMethWrapper object at 0x7f209db86810>(), <TaskWakeupMethWrapper object at 0x7f209dade190>()]> while another task <Task pending coro=<_async_setup_component() running at /workspaces/HomeAssistant/homeassistant/setup.py:170> cb=[<TaskWakeupMethWrapper object at 0x7f209db86150>()]> is being executed.

maartenbreddels commented 4 years ago

No, I don't see the error anymore, so I'm clueless.

erdewit commented 4 years ago

RuntimeError: Cannot enter into task

This error is indicative of an unpatched Task. It could be similar to the unpatched Future from #23, were it gets imported before nest_asyncio has patched asyncio.Task.

If possible, do the import and application of nest_asyncio before importing other modules.

Nereg commented 3 years ago

Same error with discord.py library.

RuntimeError: Cannot enter into task <ClientEventTask state=pending event=on_message coro=<function on_message at 0x7f2c34730c20>> while another task <ClientEventTask state=pending event=on_message coro=<function on_message at 0x7f2c34730c20>> is being executed.
Task was destroyed but it is pending!

I am patching loop before I start it by the way.

maartenbreddels commented 3 years ago

For my understanding (and possibly others), this simple script will trigger this exception:

import asyncio
import nest_asyncio

async def task1():
    print("task1 before")
    await asyncio.sleep(0.4)
    print("task1 after")

async def task2():
    print("task2 before")
    await asyncio.sleep(0.4)
    print("task2 after")

async def main():
    print("main: start")
    task = asyncio.create_task(task1())
    nest_asyncio.apply()
    asyncio.run(task2())
    print("main: end")
    await task

asyncio.run(main())

Which gives the following output:

main: start
Exception in callback <TaskStepMethWrapper object at 0x102922bb0>()
handle: <Handle <TaskStepMethWrapper object at 0x102922bb0>()>
Traceback (most recent call last):
  File "/Users/maartenbreddels/miniconda3/envs/voila-dev/lib/python3.9/asyncio/events.py", line 80, in _run
    self._context.run(self._callback, *self._args)
RuntimeError: Cannot enter into task <Task pending name='Task-2' coro=<task1() running at /Users/maartenbreddels/src/voila-dashboards/voila/cannot-enter.py:6>> while another task <Task pending name='Task-1' coro=<main() running at /Users/maartenbreddels/src/voila-dashboards/voila/cannot-enter.py:22> cb=[_run_until_complete_cb() at /Users/maartenbreddels/miniconda3/envs/voila-dev/lib/python3.9/asyncio/base_events.py:184]> is being executed.
task2 before
task2 after
main: end
# here it hangs, and after ctrl-c (twice) gives
^C^CTraceback (most recent call last):
  File "/Users/maartenbreddels/miniconda3/envs/voila-dev/lib/python3.9/asyncio/runners.py", line 44, in run
    return loop.run_until_complete(main)
  File "/Users/maartenbreddels/miniconda3/envs/voila-dev/lib/python3.9/asyncio/base_events.py", line 629, in run_until_complete
    self.run_forever()
  File "/Users/maartenbreddels/miniconda3/envs/voila-dev/lib/python3.9/asyncio/base_events.py", line 596, in run_forever
    self._run_once()
  File "/Users/maartenbreddels/miniconda3/envs/voila-dev/lib/python3.9/site-packages/nest_asyncio.py", line 87, in _run_once
    event_list = self._selector.select(timeout)
  File "/Users/maartenbreddels/miniconda3/envs/voila-dev/lib/python3.9/selectors.py", line 562, in select
    kev_list = self._selector.control(None, max_ev, timeout)
KeyboardInterrupt

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/Users/maartenbreddels/src/voila-dashboards/voila/cannot-enter.py", line 26, in <module>
  File "/Users/maartenbreddels/miniconda3/envs/voila-dev/lib/python3.9/asyncio/runners.py", line 47, in run
    _cancel_all_tasks(loop)
  File "/Users/maartenbreddels/miniconda3/envs/voila-dev/lib/python3.9/asyncio/runners.py", line 63, in _cancel_all_tasks
    loop.run_until_complete(
  File "/Users/maartenbreddels/miniconda3/envs/voila-dev/lib/python3.9/site-packages/nest_asyncio.py", line 64, in run_until_complete
    self._run_once()
  File "/Users/maartenbreddels/miniconda3/envs/voila-dev/lib/python3.9/site-packages/nest_asyncio.py", line 87, in _run_once
    event_list = self._selector.select(timeout)
  File "/Users/maartenbreddels/miniconda3/envs/voila-dev/lib/python3.9/selectors.py", line 562, in select
    kev_list = self._selector.control(None, max_ev, timeout)
KeyboardInterrupt
Task was destroyed but it is pending!
task: <Task cancelling name='Task-2' coro=<task1() running at /Users/maartenbreddels/src/voila-dashboards/voila/cannot-enter.py:6> cb=[<TaskWakeupMethWrapper object at 0x102922e50>(), gather.<locals>._done_callback() at /Users/maartenbreddels/miniconda3/envs/voila-dev/lib/python3.9/asyncio/tasks.py:764]>
sys:1: RuntimeWarning: coroutine 'task1' was never awaited

Note that this confirms what @erdewit was saying, it will be triggered when asyncio machinery wants to resume a task that is unpatched (i.e. created before .apply() was called).

Hopefully, this will help to debug similar issues.

danking commented 1 year ago

FWIW, I was encountering this issue when initializing asyncio after a loop was already running but before I created any tasks. Since 1.5.2, you can nest_asnycio.apply() outside of an event loop so there's no need to start one before you initialize nest asyncio. My package's __init__.py is now:

import nest_asyncio
nest_asyncio.apply()

# ...

And I don't see this error.

charles-cooper commented 1 year ago

@erdewit I've been looking into this and I think the problem can be solved by protecting _run_once with leave/enter current task (probably here:) https://github.com/erdewit/nest_asyncio/blob/1ddc5509132a548ff4833e1a96ef6f8c3250cbeb/nest_asyncio.py#L117-L120

this is the approach i have taken here which seems to work: https://github.com/vyperlang/titanoboa/blob/1979a4d9c57eab7b27161a857ad56dd90f7f5728/boa/integrations/jupyter.py#L159-L161

erdewit commented 8 months ago

With the implementation of @charles-cooper's idea in v1.6.0 this bug should be fixed. It can now run unpatched tasks.