4 ms·
What are the common use cases for threading in Python? I feel like that's a lower level tool than most Python projects would want, compared to asyncio or multip
by hot_gril 2y ago
What are the common use cases for threading in Python? I feel like that's a lower level tool than most Python projects would want, compared to asyncio or multiprocessing.Pool. JS is the most comparable thing to Python, and it got pretty darn far without threads.
- BugsJustFindMe 2y agoWorking with asyncio sucks when all you want is to be able to do some things in the background, possibly concurrently. You have to rewrite the worker code using those stupid async await keywords. It's an obnoxious constraint that completely breaks down when you want to use unaware libraries. The thread model is just a million times easier to use because you don't have to change the code.
- hot_gril 2y agoAsyncio is designed for things like webservers or UIs where some framework is probably already handling the main event loop. What are you doing where you just want to run something else in the background, and IPC isn't good enough?
- BugsJustFindMe 2y agoNon-blocking HTTP requests is an extremely common need, for instance. Why the hell did we need to reinvent special asyncio-aware request libraries for it? It's absolute madness. Thread pools are much easier to work with. > where some framework is probably already handling the main event loop This is both not really true and also irrelevant. When you need a flask (or whatever) request handler to do parallel work, asyncio is still pretty bullshit to use vs threads.
- hot_gril 2y agoNon-blocking HTTP request is the bread and butter use case for asyncio. Most JS projects are doing something like this, and they don't need to manage threads for it. You want to manage your own thread pool for this, or are you going to spawn and kill a thread every time you make a request?
- BugsJustFindMe 2y ago> Non-blocking HTTP request is the bread and butter use case for asyncio And the amount of contorting that has to be done for it in Python would be hilarious if it weren't so sad. > Most JS projects I don't know what JavaScript does, but I do know that Python is not JavaScript. > You want to manage your own thread pool for this... In Python, concurrent futures' ThreadPoolExecutor is actually nice to use and doesn't require rewriting existing worker code. It's already done, has a clean interface, and was part of the standard library before asyncio was.
- stavros 2y agoI feel you. I know asyncio is "the future", but I usually just want to write a background task, and really hate all the gymnastics I have to do with the color of my functions.
- BugsJustFindMe 2y agoI feel like "asyncio is the future" was invented by the same people who think it's totally normal to switch to a new javascript web framework every 6 months.
- hot_gril 2y agoJS had an event loop since the start. It's an old concept that Python seems to have lifted, as did Rust. I used Python for a decade and never really liked the way it did threads.
- zo1 2y agoPython's reactor pattern, or event loop as you call it, started with the "Twisted" framework or library. And that was first published in 2003. That's a full 6 years before Node.js was released which I assume was the first time anything event-loopy started happening in the JS world. I forgot to mention that it came into prominence in the Python world through the Tornado http server library that did the same thing. Slowly over time, more and more language features were added to give native or first-class-citizen support to what a lot of people were doing behind the scenes (in sometimes very contrived abuses of generator functions).
- kristjansson 2y agoYou don’t? concurrent.futures.ThreadPoolExecutor can get a lot done without touching async code.
- BugsJustFindMe 2y agoI am a big advocate for ThreadPoolExecutor. I'm saying it's superior to asyncio. The person I'm responding to was asking why use threads when you can use asyncio instead.
- kristjansson 2y agoAch, I posted before I saw the rest of your thread, apologies. Totally agree, concurrent.futures strikes a great balance. Enough to get work done, a bit more constrained than threads on their own. Asyncio is a lot of cud to chew if you just want a background task in an otherwise sync application
- d0mine 2y agoOrdinary CPython code releases GIL during blocking I/O. You can do http requests + thread pool in Python.
- j1elo 2y agoSo, in Rust they had threading since forever and they are now hyped with this new toy called async/await (and all the new problems it brings), while in Python they've had async/await and are now excited to see the possibilities of this new toy called threads (and all its problems). That's funny!
- BugsJustFindMe 2y agoWell, Python had threads already. This is just a slightly different form of them behind the scenes.
- dralley 2y agoYes? They have different use cases which they are good at.
- nvy 2y agoBeing hyped for <feature other languages have had for years> is totally on-brand for the Rust community.
- deleted 2y ago[deleted]
- hot_gril 2y agoThat sounds more like Golang (generics)
- hot_gril 2y agoPython is more so in the same boat as Rust. Python asyncio was relatively recent.
- throwaway81523 2y agoYeah I've never liked the async stuff. I've used the existing theading library and it's been fine, for those programs that are blocked on i/o most of the time. The GIL hasn't been a problem. Those programs often ran on single core machines anyway. We would have been better off without the GIL in the first place, but we may be in for headaches by removing it now.
- bongodongobob 2y agoSame as any other language. Separating UI from calculations is my most common need for it.
- kstrauser 2y agoIt’s hard to say because we’ve come up with a lot of ways to work around the fact that threaded Python has always sucked. Why? Because there’d been no demand to improve it. Why? Because no one used it. Why? Because it sucked. I’m looking forward to seeing how people use a Python that can be meaningfully threaded. While It may take a bit to built momentum, I suspect that in a few years there’ll be obvious use cases that are widely deployed that no one today has even really considered.
- hot_gril 2y agoMaybe a place to look for obvious use cases is in other languages. JS doesn't have threads, but Swift does. The reason I can't think of one is, free threads are most useful for full parallelism that isn't "embarrassingly parallel," otherwise IPC does fine. So far, I've rarely seen that. Best example I deal with was a networking project with lots of communication across threads, and that one was too performance-sensitive to even use C++, let alone Py. Other things I can think of are OS programming which again has to be C or Rust.
- kstrauser 2y agoThat's the kind of thing I stumble across all the time. Indexing all the symbols in a codebase: results = Counter() for file in here.glob('*.py'): symbols = parse(file) results.update(symbols) Scanning image metadata: for image in here.glob('*.png'): headers = png.Reader(image) ... Now that I think about it, most of my use cases involve doing expensive things to all the files in a directory, but in ways where it'd be really sweet if I could do it all in the same process space instead of using a multiprocessing pool (which is otherwise an excellent way to skin that cat). I've never let that stop me from getting the job done. There's always a way, and if we can't use tool A, then we'll make tool B work. It'll still be nice if it pans out that decent threading is at least an option.
- hot_gril 2y agoThese are "embarassingly parallel" examples that multiprocessing is ok for, though. There was always the small caveat that you can't pickle a file handle, but it wasn't a real problem. Threads are more useful if you have lots of shared state and mutexes. I think these examples would also perform well with GIL'd threads, since the actual Python part is just waiting on blocking calls that do the expensive work. But maybe not.