Live data from Hacker News

What Python’s asyncio primitives get wrong about shared state

inngest.com

11–20 of 55 posts

Re: What Python’s asyncio primitives get wrong about shared state

#11
post #7

[flagged]

I don't fully agree with this. Yes, surely shared mutable state can suffer from similar issues, however the cooperative nature of coroutines makes this much easier to handle. OS threads are preemptive and actually run in parallel, so you have to be aware of CPU concurrency and always be ready for a context switch.

Re: What Python’s asyncio primitives get wrong about shared state

#12

the title seems unnecessarily clickbaity. rather than "What Python's asyncio primitives get wrong" this seems more like "why we chose one asyncio primitive (queue) instead of others (event and condition)" also, halfway through the post, the problem grows a new requirement: > Instead of waking consumers and asking "is the current state what you want?", buffer every transition into a per-consumer queue. Each consumer d…

yes. I felt something very similar. I do think there is value in pointing out the pitfalls naieve users (me!) can make assuming things which aren't true about ordering of events, states. Queues with lock regions are also really nice because they are (as I understand it) very cheap: so making a thread or other concurrency primitive which writes into a queue under lock, and gets out of the way, aligns nicely with having some mothership process which reads queues under lock in a deterministic way. Actual event order can vary. but you should be able to know you had an event putting you into state A, as well as the terminal event state B you jumped into without doing work needed for state A.

Re: What Python’s asyncio primitives get wrong about shared state

#13
post #6

I think it’s not so much that the asyncio primitives got wrong about shared state, as much as is what the authors got wrong about the usage of those primitives. They are classic concurrency primitives that’s been around for almost half a century. They work as designed, but require some care to use correctly.

Agreed. This isn't an asyncio problem, it's just not how those primatices work.

Re: What Python’s asyncio primitives get wrong about shared state

#14
The one thing I wish stock python queues had an option for (async or otherwise) was some kind of explicit termination. e.g. be split into producers and consumers, and have consumers indicate iteration complete when all producers have finished (and vice versa - signal producers that all consumers have gone away). You can kind of kludge around it in one direction with stop sentinals but it's a lot more awkward to deal with - especially if your queues are bounded as then you can get into the situation where you block trying to push the stop sentinal onto the queue as it's full.

Re: What Python’s asyncio primitives get wrong about shared state

#15
post #7

[flagged]

I don't fully agree with this. Yes, surely shared mutable state can suffer from similar issues, however the cooperative nature of coroutines makes this much easier to handle. OS threads are preemptive and actually run in parallel, so you have to be aware of CPU concurrency and always be ready for a context switch.

It’s just some AI generated pseudo insight, look at the rest of their comments.

Re: What Python’s asyncio primitives get wrong about shared state

#16
post #14

The one thing I wish stock python queues had an option for (async or otherwise) was some kind of explicit termination. e.g. be split into producers and consumers, and have consumers indicate iteration complete when all producers have finished (and vice versa - signal producers that all consumers have gone away). You can kind of kludge around it in one direction with stop sentinals but it's a lot more awkward to deal…

Does task_done not do what you want?

https://docs.python.org/3/library/queue.html#queue.Queue.tas...

Re: What Python’s asyncio primitives get wrong about shared state

#17
post #7

[flagged]

I don't fully agree with this. Yes, surely shared mutable state can suffer from similar issues, however the cooperative nature of coroutines makes this much easier to handle. OS threads are preemptive and actually run in parallel, so you have to be aware of CPU concurrency and always be ready for a context switch.

Hard disagree. Co-routines are utter hell. They should have never become popular.

With traditional locking, the locked segment is usually very clear. It's possible to use race detectors to verify that objects are accessed with consistent locking. The yield points are also clear.

With async stuff, ANY await point can change ANY state. And await points are common, even sometimes for things like logging. There are also no tools to verify the consistent "locking".

So I often spend hours staring blankly at logs, trying to reconstruct a possible sequence of callbacks that could have led to a bug. E.g.: https://github.com/expo/expo/issues/39428

Re: What Python’s asyncio primitives get wrong about shared state

#18
post #4

What about a more general message-passing mailbox approach? This works really well in the Erlang/gen_server/gen_fsm world. (and in plenty of other contexts, but Erlang's OTP is still some of the best, simplest incarnation of these things)

“The problem with most programming languages is that they implement concurrency as libraries on top of sequential languages. Erlang is a concurrent language at the core; everything else is just a poor imitation implemented in libraries.” -Joe Armstrong

Re: What Python’s asyncio primitives get wrong about shared state

#19
post #7

[flagged]

Async and await is manually scheduling threads. So, if you're quite careful about what functions you call, you can arrange things so that you don't get concurrency when you don't want it.

Being careful about what functions you call is quite fragile and tedious, and doesn't compose well: what if a library changes when it adds a yield point?

Overall, async/await is a result of people programming like it's 2003, when threads were still very expensive.

Re: What Python’s asyncio primitives get wrong about shared state

#20
post #3

I'm sorry but how do you jump from 1. Polling to 2. Asyncio There's so many solutions in the middle, I have this theory that most people that get into async don't really know what threading is. Maybe they have a world vision where before 2023 python just could not do more than one thing at once, that's what the GIL was right? But now after 3.12 Guido really pulled himself by the bootstraps and removed the GIL and imp…

As of 3.14 running without the GIL is optional, but the default still has the GIL in place. 3.13 had it as experimental, but not officially supported. 3.12 and back are all GIL all day.

Python's asyncio library is single threaded, so I'm not sure why you are talking about threads and asyncio like they have anything to do with each other.

Python has been able to do more then one thing at a time for a long time. That's what the multiprocess library is for. It's not an ideal solution, but it does exist.

Post reply on HN