Posted by willm 9/2/2025
At it's heart it's kind of like an asynchronous task execution engine that sits on top of an I/O layer which allows the high-level code to coordinate the activities of various equipment. Stuff like robot arms, furnace PID controllers, gantry systems, an automatic hydraulic press/spot welder (in one case), various kinds of pneumatic or stepper actuated mechanisms, and of course, measurement instruments. Often there might be a microcontroller intermediary, but the vast majority of the work is handled by Python.
My experience with async Python has been pretty positive, and I'm very happy with our choice to lean heavily into async. Contrary to some of the comments here I don't find the language's async facilities to be rough at all. Having cancellation work smoothly is also pretty important to us and I can't say I've experienced any pain points with exception-based cancellation. Maybe we've been lucky, but injecting an exception into a task to cancel it actually does work pretty reliably. Integrating dependencies that expose blocking APIs has never been a big deal either. Usually you want to have an interface layer for every third party dependency anyways, and it's no big to deal to just write an async wrapper that uses a threads or a thread pool to keep the blocking stuff off of the main thread.
I personally think that a lot of people's negative experiences here might have more to do with asyncio than the language's async features. Prior to stepping into my current role, I also had some rough experiences with asyncio, which is why we chose to build all of our async code on top of curio. There was some uncertainty at first about how well supported it would be compared to a package in the standard library, but honestly curio is a really well put together package that just works really smoothly.
>Having cancellation work smoothly is also pretty important to us
+10000. Threads don't have good cancellation semantics, so we never had a robust solution to the "emergency shutdown" problem where you need to tell all the running equipment to stop whatever they're doing and return to safe positions.
Every day I worked on that codebase I wished it had been async from the beginning, but I couldn't see a way to migrate gradually because function coloring makes it an all-or-nothing affair.
The same thing happened with Perl and its weird threading (for different reasons, but still)... I guess Python didn't learn that lesson. Perl also gained async and coroutine support, but I think they were added a while after I left the community. I doubt many people use them today. Anyone used them and can comment on ease vs Python?
Which isn't to argue that they did a good or a bad job adding the ability to the language. It just isn't the long pole in performance concerns for most programs.
Like others are saying, if I want it fast and efficient (processing), I'll just use Go. Python isn't like JS in browsers, you don't have to use it, you have to want to use it. and the same goes with its features. Maybe if python tutorials/books and "How do i ____ in python?" search results used async, map, filter, collections,etc.. these awesome python features would be more prevalent. But, I can see how mature projects should probably mandate their usage where it makes sense.
Reminds me of how long it took some to go from Python 2 to Python 3.
I'm personally halfway through that journey (having spent like 4h reading docs/learning, on top of the development). I suspect it could have been designed in such a way so that it's less trivially easy to mess up.