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."
If this is the case then you can't use threads for this workload. If you're calling into some external code that could be doing whatever then one of the things it could be doing is holding locks. If you want a unit of execution you can murder with prejudice then you need the operating system's help which means a process.
On both Linux and Windows the situations where you can safely kill a thread is when you have complete control and knowledge of what's running in it, the very opposite of when people want to be able to kill threads.
- runtime optionally type checked interfaces
- make depending on system python an antipattern
- a reasonable package manager with lockfiles and transitive dependency versions
- package org namespaces
- steps towards hermetic builds with less linking against system libraries and dependencies
- cleanup and slimming down of the standard library. Removal of cruft. Less "batteries included" so people lean more on packages and enforcing good practices with packages.
Python is too flexible. It produces sloppy code.
And in no world are Python builds and dependencies solved. It's a major headache.
For that matter, one of those dependencies, `pyparsing`, is around 10k lines installed (and the repository is much larger with tests etc.). That's with it not having any dependencies of its own.
There is no real barrier anywhere around the 1k loc mark. The problems large projects run into have more subtle causes.
Look, is correct to understand that the BEST way, the BEST refactoring of all, is to change to a language + libraries that fix core issues (similar how you can't outrun a bad diet you can't outrun bad semantics)
BUT, also change it means lose a lot of nice things.
For example I move from python to F# and then Rust, for what I say that is now the best overall decision at all, BUT I miss dearly Django (and instant run and REPL)
IF I could get Django (that means transitively use python) and get better type system and perf from it, I could consider it and surely use it, like "python get as swift or go but with rust algebraic types, whatever it means to get here and yet is Django and python. ok?
Is unreasonable? but sincerely, it will nice if the best ideas get retrofitted in other languages because, well, I wish everyone get as more nice things as possible instead of keep with suboptimal options (that is what I say: breaking languages is not something that must be forbidden forever)
Is unreasonable? (I say again) could be, but I think is a good thing to explore. Maybe is not that much, and if at the end things get better, great!
> They do not enforce it. It's not about "can do". It's about defaults and enforcing stricter standards.
How exactly do you want to "enforce" an "optional" runtime type check for an interface, that is different from opting in by calling `isinstance`?
For that matter, `TypeError` exists and is raised non-optionally by all sorts of things.
> And in no world are Python builds and dependencies solved. It's a major headache.
For your specific set of dependencies, perhaps. Lots of people are using Python just fine. A large majority of what I'm interested in using would install fully (including transitive dependencies) from pre-built wheels on my system; and of those wheels, a large majority contain only Python code that doesn't actually require a build step. (Numpy is the odd one out here.)
In fact, of the top 10 largest packages in my system's `dist-packages` (all stuff that came provided with my Linux distro; I respect PEP 668 and don't let Python native packaging tools touch that environment), at least 9 have wheels on PyPI, and 4 of them have `none-any` wheels. (And of course, tons of the smaller ones are pure Python - there's simply no room for a compiled binary there.)
---
For posterity -
make depending on system python an antipattern
uv is virtual env, uv managed python executable first,
opt in to system python packages only a reasonable package manager with lockfiles and transitive dependency versions
uv.lock, check. I think base pip also has transitive dependencies, though, and has since 2020? steps towards hermetic builds with less linking against system libraries and dependencies
I know there's build isolation for dependencies in uv, I'm not sure it solves the problem you haveWhat is it you mean by package org namespaces?
> What is it you mean by package org namespaces?
eg. `google/protobuf`. An organization would parent all of its packages under its namespace.
> uv is virtual env, uv managed python executable first, opt in to system python packages only
A project should blow up if you attempt to use system python. It should not work.
`python main.py` should handle all of this for you.
An ideal Python would work like Rust's cargo. And there would be only one way to use it.
You keep seeing this come up because it's still a systemic issue with the ecosystem. Python needs to enforce this top down.
If you're talking about what you write in the code to import it, nothing prevents anyone from doing this. They just don't, because PyPI is a free-for-all by design.
If you're talking about names used on PyPI, see https://peps.python.org/pep-0752/.
But this is not a language feature.
> A project should blow up if you attempt to use system python. It should not work.
Why?
> `python main.py` should handle all of this for you.
How could it, given the issues you've identified?
> You keep seeing this come up because it's still a systemic issue with the ecosystem. Python needs to enforce this top down.
A very large fraction of Python users (whom you'll likely never hear from because they have their own ways of sharing code amongst themselves) actively don't want that kind of enforcement.
A project should blow up if you attempt to use system python. It should not work.
Disagree here - an environment is an environment. Yes, the system python environment is kind of shit, but it does provide one - if a package cares about where exactly it gets dependencies, other than "here's a directory with packages", it's doing something wrong. I'm not sure how you'd enforce that, as nice as it sounds from the point of view of getting system python to go away. `python main.py` should handle all of this for you.
Have you seen https://docs.astral.sh/uv/guides/scripts/ ?Just to be clear - I agree with you. My impression of the python packaging ecosystem has been that it's kind of shit, various tries have been made at fixing it with various tools, all of them have had issues with one workflow or another. But things are now trending in a much more positive direction.
Pip has attempted to resolve and install transitive dependencies since even before 2020. That's just when they introduced a new, backtracking resolver (which can be slow because it is thorough and simple-minded about its backtracking).
"hermetic builds" sounds to me like it's referring to packages that don't depend on system binaries being present, by the magic trick of separately providing them (even if redundant). That's... just a wheel.
But also: currently, Python 4 is out of the question, and even if it were in play, "we should take this opportunity to integrate package management into the language" would be completely out of the question. That's just not how Python's politics work internally. There is generally pretty broad agreement anyway that the reasons packaging problems are hard to solve in Python (in the places where they actually are) are: 1) people don't agree on the design for a solution; 2) all that code in other programming languages that people want to interface with from Python (which, to be clear, is not something they're trying to get rid of); 3) backwards compatibility concerns. Making a clean break is not going to help with the first two and is directly opposed to the third.
The tragedy of Python 3 is that they made the community go through a billion dollar migration but didn't tackle any of the hard stuff. And the reason they didn't was the Perl 6 debacle. So it's all Larry Wall's fault.
Python could do with more major version upgrades, but small scoped upgrades that only change tiny, manageable pieces. Forcing a good package manager on all Python developers would be a good candidate for this.
No, just no. If anything, Python needs more batteries built-in.
I have a couple of small tools which work well. One is basically a 200 loc script that coverts files.
The moment you need multiple files, the project is probably big enough where you really need a strong type system.
Java and C# fit extremely well for this. Both have caught up in terms of ease of use. The latest .net let's you run a C# file individually like a bash script.
The gift and curse of python is that it's really easy to do a lot. So you can be sloppy , just tossing stuff in, up until issues start to arise. Next thing you know you have a giant code base no one has any chance of understanding.
Still, it's a great first language. You can make small tools within a month. C isn't nearly as forgiving.
If you love the Python syntax, Nim is here.
If C and Python are the only options I would strongly vote for C being the first. It will weed out those who are unfit.
Myself I use many languages including Python but I started programming by entering machine codes in hex. Obviously I do not do it now but I think it did benefit me in general.
Python can help a bartender write a small application to track her stock for example. In fact with a bit of computer vision this can work very well.
I originally just wanted to make small games, I was hacking together sloppy JavaScript. I don't like gate keeping.
The future is probably even a higher level language than Python. Maybe an embedded llm that sorta decides what to do at runtime.
For larger projects, Go seems to follow the "Zen of Python" better than Python itself nowadays.
I made those changes while still targeting 2.7: around 2018 I was writing code for 2.7 that was forward-compatible with 3.x, as was common at the time. Since then, f-strings have been worth adding to my toolbox - most of Python 3's other new features haven't been.
Rust.
Yes, it clearly has a sharper learning curve than Python. But I think idiomatic Rust feels a lot like a good Python implementation of the same thing would, in ways I can’t quite explain. The borrow checker is certainly something to come to grips with, but it also nudges you to write code the way you should probably be writing it anyway. Don’t pass complex structures around and mutate them everywhere. Don’t return 5 kinds of object from the same function. Don’t go crazy with inheritance vs plain, understandable, testable functions.
Rust just feels right to my Pythonista brain.
- 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.
"creating the first ever first-class language with green-threading at its core."
... isn't that what Go is? I think out of all languages I use extensively, Go is the only one that doesn't suffer from the sync/async function coloring nightmare.
gevent's monkey-patching might be hacky, but an official implementation of stackful coroutines (similar to Lua's) need not have been.
Instead, stackless coroutines were chosen - maybe on merit, but also maybe because C#'s async/await keywords were in-vogue at the time and Python copied them.
I'm with you that function "coloring" (monads in the type system) can be unergonomic and painful.
> ... isn't that what Go is? I think out of all languages I use extensively, Go is the only one that doesn't suffer from the […] coloring nightmare.
Because it doesn't have Future/Promise/async as a built-in abstraction?
If my function returns data via a channel, that's still incompatible with an alternate version of the function that returns data normally. The channel version doesn't block the caller, but the caller has to wait for results explicitly; meanwhile, the regular version would block the caller, but once it's done, consuming the result is trivial.
Much of the simplicity of Go comes at the expense of doing everything (awaiting results, handling errors, …) manually, every damn time, because there's no language facility for it and the type system isn't powerful enough to make your own monadic abstractions. I know proponents of Go tend to argue this is a good thing, and it has merits. But making colorful functions wear a black-and-white trenchcoat in public doesn't solve the underlying problem.
(goroutines are nice, though.)
But in Go, it's very easy to do this; you can just do "result := <- ch" to obtain the value from a channel in synchronous code. (This blocks the thread, but in Go's concurrency model this isn't a problem, unlike in JavaScript.) Similarly it's very easy to take a synchronous function and do "go func() { ch <- myFunction() }()" to make it return its result in a channel.
> 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...
I do. To be clear: I'm not saying that (well-designed versions of) pattern-matching will become less useful over time, but that they will become less fashionable.
Python will then, no doubt, add another language construct to appeal to those who choose languages solely based on a checklist of features.
I recently chased down a bug where something was accidentally made a class variable because a type hint was left off it by accident and it clicked for me that Python is not the same language I loved at the start of my career.
Same, but I don't think that's the direct cause. Guido was actually in favor of all these features (as well as Walrus, of course) - so it's not like he would have vetoed them if he were still BDFL.
That's the reverse situation to one I've come across - a novice accidentally wrote `a : 4` instead of `a = 4` and was surprised that `a` was still undefined. There was no error because the `4` was interpreted as a type hint.
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.
TZubiri•6h ago
zdragnar•5h ago
I'll never forget one Java developer who transitioned to JS frontend work (pre-typescript days). Try/catch everywhere.
There's a semi-accurate mindset that "good developers are good in any language" as if software engineers are fungible resources, but the transition time to a novel paradigm isn't really well appreciated.
mbb70•5h ago
The culture and idioms of Java impose great constraints than syntax.
Not meant as a knock on Java or Java developers.
zahlman•4h ago
Including in the standard library (the most egregious examples being `logging` and `unittest`).
And another big problem is how much C is written in it, even when the project also contains actual C.