Remix.run Logo
svieira 2 days ago

I used to keep plugging Unyielding [1] vs. What Color Is Your Function [2] as the right matrix to view these issues within. But then Notes on structured concurrency [3] was written and I just point to that these days.

But, to sum it all up for those who want to talk here, there are several ways to look at concurrency but only one that matters. Is my program correct? How long will it take to make my program correct? Structured concurrency makes that clear(er) in the syntax of the language. Unstructured concurrency requires that you hold all the code in your head.

[1]: https://glyph.twistedmatrix.com/2014/02/unyielding.html

[2]: https://journal.stuffwithstuff.com/2015/02/01/what-color-is-...

[3]: https://vorpus.org/blog/notes-on-structured-concurrency-or-g...

heisenzombie 2 days ago | parent | next [-]

I'll second the plug for structured concurrency (and specifically the Trio [1] library that the author wrote.

[1] https://github.com/python-trio/trio

vpribish 2 days ago | parent [-]

If I ever want to use async in python again i'm going with Trio.

stephenlf 2 days ago | parent | prev | next [-]

Man, that Trio [3] read was great. When we demand that all concurrent tasks must join, then we can better reason about our programs.

I already kinda had this idea while working with Rust. In Rust, Futures won’t execute unless `await`ed. In practice, that meant that all my futures were joined. It was just the only way I could wrap my head around doing anything useful with async.

VonTum 2 days ago | parent | prev [-]

In [3], isn't there a pretty trivial exploit to get a "background task reads from closed file" again?

  async with mk_nursery() as nursery:
    with os.fopen(...) as file:
      nursery.start_soon(lambda: file.read())
The with block may have ended before the task starts...