21 comments

[ 2.8 ms ] story [ 44.8 ms ] thread
Only experience with this thing was when working with a node dev that was trying out python. What a mess, he didnt quite get how processes or threads worked, just learned node's model event / promise models and brought them to python
> In the traditional model of concurrent programming using threads, there is no clean way to do cancellation.

The only solution is the one being complained about--for a thread to voluntarily check if it needs to be cancelled.

Java deprecated stop() for good reasons.

"Those who cannot remember the past are condemned to repeat it."

Agree. If genuine pre-emptive cancellation from the outside is needed, all languages support the primitive which allows that: a process.

Many of the tradeoffs that come from using a process rather than a thread descend directly from that property of support for arbitrary-point cancellation.

the real problem is python, great at the start of a project, by the end i am dying to rewrite in java.
This seems like a microcosm of the general design problems that pervade Python. It is a fundamentally quirky language.
I really wish the community had coalesced around gevent.

- no async/await, instead every possible thing that could block in the standard library is monkey-patched to yield to an event loop

- this means that you can write the same exact code for synchronous and concurrent workflows, and immediately get levels of concurrency only bounded by memory limits

- you'll never accidentally use a synchronous API in an async context and block your entire event loop (well, you can, if you spin on a tight CPU-bound loop, but that's a problem in asyncio too)

- the ecosystem doesn't need to implement libraries for asyncio and blocking code, everything just works

There's a universe where the gevent patches get accepted into Python as something like a Python 4, breaking some niche compatibility but creating the first ever first-class language with green-threading at its core.

But in this universe, we're left with silly things like "every part of the Django ecosystem dealing with models must be rewritten with 'a' prefixes or be abandoned" and it's a sad place indeed.

I worked quite a bit with gevent'd code about 10+ years ago and also agree. Dealing with function coloring is incredibly non productive. This is one of the things "go" got right.
Agreed. I chose gevent over asyncio for a backend in 2019, and we still using it. Works pretty well. No plans to phase out gevent just yet.

Though the community has clearly centered on asyncio by now. So if I were to start a new backend today, it would reluctantly be asyncio. Unfortunately...

> asyncio has so many sharp corners and design issues [...] bordering on being fundamentally broken

> other languages and libraries did what asyncio does significantly better

> it is baffling how the library made it out of provisional status with such glaring flaws

Unfortunately this seems common in Python 3.x. The hype-cycle focuses on a feature from another language(s), and Python rushes to add its own version without sufficient attention to its design, nor how the feature complements the rest of the language (if at all).

Async, type hints and pattern matching all fit this description. `match` is probably the worst offender - it seems to have been added mainly so that novices choosing a language will not veto Python because it's missing the current feature-du-jour. [0]

Type hints are at least having their flaws addressed - but the flaws can't be removed due to back-compat. This leads to a C++-like situation of "this is the modern way, these other approaches are deprecated". So much for "one way to do it".

[0] https://discuss.python.org/t/pep-8012-frequently-asked-quest...

In my experience, the key to using asyncio is to use anyio. Anyio is an interface that you can use ontop of asyncio and fixes most of its shortcomings.

https://anyio.readthedocs.io

Asyncio is too dull. Twisted for the win! My favourite insane package of wonders.
And the best way to write unmaintainable and undebuggable spaghetti code.
For the (brief) C comparison, I'm really not sure why this talks about `pthread_kill` but not `pthread_cancel` ...
`pthread_cancel` still has most of the issues described.
Sir, this is Wendy's.

I have a feeling that the core issue is that author is trying to implement complex communication mechanisms with a tool that was designed for much more basic usage. I don't understand why half of the article is about cancellations while cancellations as a concept are wrong. Have you ever tried to cancel peeing mid-pee? It just doesn't work.

Not sure if the other half of the article is worth reading if first half has completely wrong premise. Or does this guy live in some utopian future where it's reasonable to assume that everything can be cancelled at any point.

“Any sufficiently complicated concurrent program in another language contains an ad hoc informally-specified bug-ridden slow implementation of half of Erlang.” – Virding’s first rule of programming
Oh cool. I wrote this. 100% hit rate on random posts of mine ending up on HN.
As somebody that has written couple of services with Twisted in the late '00s, I feel asyncio a breath of fresh air. This not means that it's perfect, but it's a lot more usable than Twisted. I know that it's not possible, but I would like to have in Python something similar to goroutines, waitgroups and channels that Go has.
A big issue with asyncio is IME the documentation. The main document is a tutorial-style tour of the features, scarcely mentioning the important details. These are often hidden in comments on seemingly unrelated features or, more likely, reddit and SE.

Some Python documentation indeed includes a tutorial, but also has a comprehensive documentation. This is not my experience with asyncio

I'm working on an ML platform in Elixir. Orchestrating CPU-intensive Python processes is central to the project, so I created a session based pooler called `snakepit` [1].

The latest revision is building a batteries-included gRPC Python bridge that enables streaming, bi-directional tool use, as well as an innovative variables feature for experimental ML inspired by ideas from DSPy's team.

One of the later project goals: A Python client that can manage the Elixir orchestrator that manages pools of Python, in a distributed environment. Maybe I'll call that submodule `snakepits`. In this embodiment, it will be an effective albeit much more sophisticated replacement for `asyncio` for some use cases.

[1] https://github.com/nshkrdotcom/snakepit