Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Await an async function in Python debugger

Is it possible to await arbitrary calls to an async function when inside a Python debugger?

Say I have the following code in some main.py file:

import asyncio

async def bar(x):
    return x + 1

async def foo():
    import ipdb; ipdb.set_trace()

asyncio.run(foo())

Now I want to test calling bar() with some argument inside the debugger to test the results. The following happens:

$ python3 main.py
> /Users/user/test/main.py(8)foo()
      7     import ipdb; ipdb.set_trace()
----> 8     return None
      9

ipdb> bar(1)
<coroutine object bar at 0x10404ae60>
main.py:1: RuntimeWarning: coroutine 'bar' was never awaited
  import asyncio
RuntimeWarning: Enable tracemalloc to get the object allocation traceback
ipdb> await bar(1)
*** SyntaxError: 'await' outside function

Of course, I can get around this by having x = await bar(1) above my ipdb.set_trace(), and then inspecting the results, but then I can't try calling my functions in real time while the debugger is active.

like image 233
Ivan Gozali Avatar asked Aug 17 '19 01:08

Ivan Gozali


People also ask

Can you await an async function?

The await operator is used to wait for a Promise and get its fulfillment value. It can only be used inside an async function or a JavaScript module.

Is there async await in Python?

Python's asyncio package (introduced in Python 3.4) and its two keywords, async and await , serve different purposes but come together to help you declare, build, execute, and manage asynchronous code.

How is async await implemented in Python?

The await keyword can be put in front of any async coroutine-based function to pause your code on that line until the coroutine fulfills. Then, return the resulting value. In simpler words, you can think of the await keyword as the place where it is safe for one coroutine to move to another coroutine.

How do you call a async function in Python?

To run an async function (coroutine) you have to call it using an Event Loop. Event Loops: You can think of Event Loop as functions to run asynchronous tasks and callbacks, perform network IO operations, and run subprocesses. Example 1: Event Loop example to run async Function to run a single async function: Python3.


2 Answers

Seems like there's starting to be more support for this feature since Python 3.8. In particular, look at this issue bpo-37028

If you're still on Python 3.7, maybe aiomonitor could have something that supports this feature to a certain extent.

like image 70
Ivan Gozali Avatar answered Oct 02 '22 04:10

Ivan Gozali


Here a modified version of what I posted at https://stackoverflow.com/a/67847257/893857 since it also solves this problem.

I found a solution using nest_asyncio. If one has the following async example script:

import asyncio
import nest_asyncio


async def bar(x):
    return x + 1

async def foo():
    import ipdb; ipdb.set_trace()


if __name__=="__main__":
    loop = asyncio.get_event_loop()
    nest_asyncio.apply(loop)
    loop.run_until_complete(foo())

One can then do:

      8 async def foo():
----> 9     import ipdb; ipdb.set_trace()
     10 

ipdb> loop = asyncio.get_event_loop()
ipdb> loop.run_until_complete(bar(1))
2

Admittedly it is a bit more tedious then await bar(1) but it gets the job done. Hopefully a more elegant solution will come up in the future.

like image 44
M.D. Avatar answered Oct 02 '22 05:10

M.D.