This project has been archived by its maintainers, and is no longer receiving any updates.
Await, What?
Tells you what waits for what in an async/await program.
Python 3.10.0a1
It seems the API was changed in 3.10 and the C extension doesn't compile. I'll investigate...
Alpine
You'll need apk add build-base openssl-dev libffi-dev
2019 Sprint Setup
Comms: https://gitter.im/awaitwhat/community
- Python 3.9, Python 3.8 (preferred) or Python 3.7
- Your platform dev tools (compiler, etc).
- Ensure that
pythonis 3.9 or 3.8 or 3.7 - Install
poetry - Install
graphviz - Clone this repository
- Look at tests
- Look at issues
> python --version
Python 3.9.0b4 #🧡
Python 3.8.4 #👌
> dot -V
dot - graphviz version 2.40.1
> curl -sSL https://raw.githubusercontent.com/sdispater/poetry/master/get-poetry.py | python
# add ~/.poetry/bin to your PATH
> git clone git@github.com:dimaqq/awaitwhat.git
> cd awaitwhat
~/awaitwhat (dev|✔) > poetry shell # creates a venv and drops you in it
(awaitwhat-x-py3.9) ~/awaitwhat (dev|✔) > poetry install # installs projects dependencies in a venv
(awaitwhat-x-py3.9) ~/awaitwhat (dev|✔) > poetry build # builds a C extension in this project
(awaitwhat-x-py3.9) ~/awaitwhat (dev|✔) > env PYTHONPATH=. python examples/test_shield.py | tee graph.dot
(awaitwhat-x-py3.9) ~/awaitwhat (dev|✔) > dot -Tsvg graph.dot -o graph.svg
(awaitwhat-x-py3.9) ~/awaitwhat (dev|✔) > open graph.svg # or load it in a browser
TL;DR
Say you have this code:
async def job():
await foo()
async def foo():
await bar()
async def bar():
await baz()
async def baz():
await leaf()
async def leaf():
await asyncio.sleep(1) # imagine you don't know this
async def work():
await asyncio.gather(..., job())
Now that code is stuck and and you want to know why.
Python built-in
Stack for <Task pending coro=<job() …> wait_for=<Future pending cb=[<TaskWakeupMethWrapper …>()]> cb=[…]> (most recent call last):
File "test/test_stack.py", line 34, in job
await foo()
This library
Stack for <Task pending coro=<job() …> wait_for=<Future pending cb=[<TaskWakeupMethWrapper …>()]> cb=[…]> (most recent call last):
File "test/test_stack.py", line 34, in job
await foo()
File "test/test_stack.py", line 38, in foo
await bar()
File "test/test_stack.py", line 42, in bar
await baz()
File "test/test_stack.py", line 46, in baz
await leaf()
File "test/test_stack.py", line 50, in leaf
await asyncio.sleep(1)
File "/…/asyncio/tasks.py", line 568, in sleep
return await future
File "<Sentinel>", line 0, in <_asyncio.FutureIter object at 0x7fb6981690d8>: …
Dependency Graph
References
https://mail.python.org/archives/list/async-sig@python.org/thread/6E2LRVLKYSMGEAZ7OYOYR3PMZUUYSS3K/
Hi group,
I'm recently debugging a long-running asyncio program that appears to get stuck about once a week.
The tools I've discovered so far are:
- high level:
asyncio.all_tasks()+asyncio.Task.get_stack()- low level:
loop._selector._fd_to_keyWhat's missing is the middle level, i.e. stack-like linkage of what is waiting for what. For a practical example, consider:
async def leaf(): await somesocket.recv() async def baz(): await leaf() async def bar(): await baz() async def foo(): await bar() async def job(): await foo() async def work(): await asyncio.gather(..., job()) async def main(): asyncio.run(work())The task stack will contain:
- main and body of work with line number
- job task with line number pointing to foo
The file descriptor mapping, socket fd,
loop._recv()and aFuture.What's missing are connections
foo->bar->baz->leaf. That is, I can't tell which task is waiting for what terminalFuture.Is this problem solved in some way that I'm not aware of? Is there a library or external tool for this already?
Perhaps, if I could get a list of all pending coroutines, I could figure out what's wrong.
If no such API exists, I'm thinking of the following:
async def foo(): await bar() In [37]: dis.dis(foo) 1 0 LOAD_GLOBAL 0 (bar) 2 CALL_FUNCTION 0 4 GET_AWAITABLE 6 LOAD_CONST 0 (None) 8 YIELD_FROM 10 POP_TOP 12 LOAD_CONST 0 (None) 14 RETURN_VALUEStarting from a pending task, I'd get it's coroutine and:
Get the coroutine frame, and if current instruction is
YIELD_FROM, then the reference to the awaitable should be on the top of the stack. If that reference points to a pending coroutine, I'd add that to the "forward trace" and repeat.At some point I'd reach an awaitable that's not a pending coroutine, which may be: another
Task(I already got those), a low-levelFuture(can be looked up in event loop), anEvent(tough luck, shoulda logged allEvent's on creation) or a dozen other corner cases.What do y'all think of this approach?
Thanks, D.
Metadata
Release files for awaitwhat 21.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| awaitwhat-21.1.tar.gz | 9.3 kB | Without provenance | Details for awaitwhat-21.1.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| awaitwhat-21.1-cp39-cp39-macosx_10_16_x86_64.whl | CPython 3.9 | CPython 3.9 | macOS 10.16+ x86-64 | Details for awaitwhat-21.1-cp39-cp39-macosx_10_16_x86_64.whl |
Total release size: 27.1 kB
Release files / awaitwhat-21.1.tar.gz
| Download URL | awaitwhat-21.1.tar.gz |
|---|---|
| Size | 9.3 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
4c84ab717d1781c7ce01fcaa51cef35a63a10f3ce8f64609c8294c0fc6b6ae99
|
|
BLAKE2b-256 checksum How to use checksums |
08fd2c94a7ed767a24c73f1c85016825a1474d2f2ba27168658af81173d8068e
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
poetry/1.1.7 CPython/3.9.5 Darwin/20.5.0
|
Release files / awaitwhat-21.1-cp39-cp39-macosx_10_16_x86_64.whl
| Download URL | awaitwhat-21.1-cp39-cp39-macosx_10_16_x86_64.whl |
|---|---|
| Size | 17.8 kB |
| Tags | CPython 3.9 macOS 10.16+ x86-64 |
|
SHA-256 checksum How to use checksums |
dc2c534603878d44947511565fa638aa9af1b247a58cd2d6290def247372fd33
|
|
BLAKE2b-256 checksum How to use checksums |
bb81d0cdd07d4256cda4463dbec4a912d2f6a3947b7db97b9f986d0147fea222
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
poetry/1.1.7 CPython/3.9.5 Darwin/20.5.0
|
Security for awaitwhat 21.1
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.