Skip to content

Comms with async functions #868

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

Open
mlucool opened this issue Nov 1, 2022 · 5 comments
Open

Comms with async functions #868

mlucool opened this issue Nov 1, 2022 · 5 comments
Labels

Comments

@mlucool
Copy link
Contributor

mlucool commented Nov 1, 2022

Hi,

Is there a recommendation for when a comm needs to call an async function. While support for #433 would be ideal, the usecase is that there is some async def foo() that needs to be called from within a comm. For now, the best way to work around this was to make it synchronous via (using ideas from ipython/ipython#13670 (comment)):

import nest_asyncio
nest_asyncio.apply()
asyncio.run(foo())

This seems to work, but I didn't know if there was a better way.

@blink1073
Copy link
Contributor

Hi @mlucool, you could use a pattern like the following to avoid using nest_asyncio:

import asyncio
loop = asyncio.get_event_loop()
loop.create_task(foo())

The above will only work if there is an asyncio loop running, which is the case when run in ipykernel.

Assuming python/cpython#98440 gets merged instead of python/cpython#93453, this pattern will continue to work in Python 3.12+.

@graingert
Copy link

@blink1073 python/cpython#98440 made no such changes to what happens with get_event_loop when an event loop is already running. You only need to use asyncio.create_task(foo()) in this case

@blink1073
Copy link
Contributor

If I understand correctly, asyncio.create_task(foo()) will always work now with IPython, since an event loop is installed but potentially not running by default. I'll wait until I can actually test it with a patched version of CPython to verify.

@blink1073
Copy link
Contributor

No, I just tried Python 3.11.1 which has the backport. As expected, fut = asyncio.Future() no longer raises a RuntimeWarning because IPython has an event loop installed but not running. However, asyncio.create_task(foo())
raises:

---------------------------------------------------------------------------
RuntimeError                              Traceback (most recent call last)
Cell In[6], line 1
----> 1 asyncio.create_task(foo())

File /Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/asyncio/tasks.py:371, in create_task(coro, name, context)
    366 def create_task(coro, *, name=None, context=None):
    367     """Schedule the execution of a coroutine object in a spawn task.
    368
    369     Return a Task object.
    370     """
--> 371     loop = events.get_running_loop()
    372     if context is None:
    373         # Use legacy API if context is not needed
    374         task = loop.create_task(coro)

RuntimeError: no running event loop

However, using the following still works and does not give a warning:

In [7]: loop = asyncio.get_event_loop()
   ...: loop.create_task(foo())
Out[7]: <Task pending name='Task-436' coro=<foo() running at <ipython-input-5-f3ec22a30cd8>:1>>

@blink1073
Copy link
Contributor

I get the same error with Python 3.12.0a3 and asyncio.create_task(foo())

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants