
Waiting in Asyncio - BerislavLopac
https://hynek.me/articles/waiting-in-asyncio/
======
j88439h84
Trio is a much simpler design that's just as powerful as `asyncio`. It has
exactly one way to wait for a task: await it.

[https://trio.readthedocs.io/](https://trio.readthedocs.io/)

For a group of tasks, use a nursery.

Edit: correction

~~~
nerdwaller
To save others the search regarding a nursery:
[https://trio.readthedocs.io/en/stable/tutorial.html#okay-
let...](https://trio.readthedocs.io/en/stable/tutorial.html#okay-let-s-see-
something-cool-already)

I don’t see much more useful here than understanding the asyncio primitives
and available synchronization abstractions, just a different API mostly
overlapping the same need

To be clear, trio also has more than one way to wait for a task - any await is
the same (e.g. `await trio.sleep(N)` (e.g. `await asyncio.sleep(N)`). I think
maybe you’re getting at waiting for a group of tasks?

~~~
j88439h84
I'm on mobile so cant type a long response but IME its quite different in
terms of ease of use, complexity, and correctness.

For a theoretical take see

[https://vorpus.org/blog/notes-on-structured-concurrency-
or-g...](https://vorpus.org/blog/notes-on-structured-concurrency-or-go-
statement-considered-harmful/)

To be precise, to wait for a task its actually just await. Theres no
ensure_future etc. Trio doesn't have the concept of futures or promises at
all, and await f() is treated as a single piece of syntax, so in practice it
doesn't have "awaitables" either.

~~~
naasking
An interesting idea, essentially Trio restructures concurrent code to more
closely resemble parallel code, which innately has the property that the
concurrency is not observable, ie. the black box property. It's a little more
general than strict parallel code though because task spawning is reified as a
first class value via which the program can spawn new tasks.

I'm not sure it's totally novel though. For instance, C# has AsParallel()
extensions which let you run collection operations in parallel (similar
functions in Haskell too). It has the same black box behaviour described by
the article, and there's an equivalence between direct control flow in code
and indirect control flow reified as a data structure, ie. Haskell's case that
lazy evaluation and lists are the only control flow construct you need.

Still, it's an interesting imperative incarnation of the idea!

------
t-writescode
There were 2 things about asyncio that I really didn't like:

1\. the library constantly changed under our feet and that also meant that
Stack Overflow articles were all over the place between Python 3.5 and 3.7.

2\. I don't think I've ever successfully mocked an async function in python.
This made testing async code in python, especially mocking responses from an
async web call (an obvious use of async in python) very difficult, if memory
serves me. It's been several months since I've used async in python (job
change) though, so maybe it's gotten easier or maybe the exact mocking test
case issues I had are different drom what I think.

~~~
xtreak29
From Python 3.8 there is AsyncMock :
[https://docs.python.org/3/library/unittest.mock.html#unittes...](https://docs.python.org/3/library/unittest.mock.html#unittest.mock.AsyncMock)
. It's also available on mock backport from pypi for other versions. It's
based on asynctest module.
[https://pypi.org/project/asynctest/](https://pypi.org/project/asynctest/)

------
war1025
We've been using Twisted at work for over a decade. We are finally completing
our upgrade to python3 after much effort and pain. That means we are starting
to look into the native async functions in python3.

What I realized the other day is that Twisted treats everything like an
asyncio Task. That seems to make most of the more confusing gotchas just
disappear. I suppose it's a matter of what you're used to though.

------
dilandau
All these subtleties and gotchas signify, to me, a shit implementation and a
fragmented interface. The exact opposite of the Zen of python.

~~~
hedora
Can you give a practical example of a library or python subsystem that lives
up to the “Zen of python” you are referring to?

~~~
j88439h84
There are lots. `requests` is the most famous.

~~~
uranusjr
requests is “clean enough” if you only use the highest level functionalities
like making stateless requests and read out the response. I wouldn’t say it
fits the description once you go past that.

Zen of Python is an illusion. Complex things are complex, there’s simply no
way to have an interface that’s always clean, useful, and maintainable.

~~~
j88439h84
These are about priorities, not about achieving perfection. It is easy to
distinguish different pieces of software on these dimensions. For example:

"Beautiful is better than ugly." Requests is more beautiful than urllib2.

"Simple is better than complex." Trio is simpler than asyncio.

"Readability counts." Python is more readable than C++.

"There should be one-- and preferably only one --obvious way to do it."
''.join(strings), not sum(strings, '').

Note what _isn 't_ in the Zen of Python: performance, close-to-the-metal-ness,
correctness, portability.

Python often fails to live up to its values, but that doesn't make them
meaningless.

------
toolslive
\- wouldn't it be nice if you could figure out if a function/method could
block?

\- What's a good strategy to migrate a larger python codebase towards asyncio
? (Haven't found any)

~~~
ghostwriter
> What's a good strategy to migrate a larger python codebase towards asyncio ?
> (Haven't found any)

use gevent instead

------
erdewit
One other gotcha with asynio.gather is that is that it _starts_ the awaitables
in a random order.

------
harpyeagle
Thanks! I'm definitely going to keep this under my pillow.

------
justaguy88
It's python. ..that took too long to figure out

~~~
amelius
Yes, it should be in the title.

