I’ve tried all the options and my view is unless you test bundling from the start of the project you’re in for a world of hurt, either having to manually patch packages (ntlk); or produce executables that are missing dependencies.
It’s the main reason I’m looking at switching to Go for these kinds of apps. Python should have a working solution as part of the standard library.
Agreed. Dotnetcore, rust, golang all have an out of the box option for shipping binaries. I really enjoy using python to get something done fast but I'm not a fan of the whole ecosystem.
Where Python fails is dependency management and packaging, much like this xkcd portrays: https://xkcd.com/1987/
It's a shame, too, because the language is perhaps one of the easiest to read, write and just generally develop in, and has a really rich ecosystem which can be leveraged to great success.
I've felt for a long time that language specs should be more clearly separated from their runtimes. Why couldn't we have statically compiled Python? Why did native Java executables need something like GraalVM be painstakingly introduced over many years, and even then fail to work properly whenever dynamic loading is involved (e.g. Spring framework)? The answer probably lies in the insane complexity all of that involves and making these decoupled isn't feasible with our current tooling, unless we want to spend a decade developing a new language/runtime like that.
> [Java/GraalVM natively compiled apps] fail to work properly whenever dynamic loading is involved (e.g. Spring framework)
What do you exactly expect if Spring/Java heads insist on late binding and religously exercise "dependency injection"? You can configure native-image reflection based on a closed-world assumption wrt what classes are known at compile-time, but TBH it seems futile if devs use shit-tonnes of annotation, dynamisms, and reflection magic. Or, as someone else here said, "in idiomatic Java/Spring code, behavior is expressed through anything and everything, except actual Java code."
I expect the Spring framework to hopefully some day fade into obscurity and die.
Its ample usage of reflection is just evil, polluting your stack traces with needless proxy classes and abstraction upon abstraction upon abstraction. You can debug code pretty easily, whereas doing that with annotations or XML that gets parsed and executed by code that you know nothing about leaves you in hopeless situations more often than you'd like. Instead of solving business problems, you end up solving whatever it is that Spring wants you to do.
Thus, most of your post is spot on. Rather often, it is the frameworks that are keeping us in a pretty unhappy place. In contrast, languages like Go feel a bit more pure in that regard, even generics were only added recently. Not giving the framework developers tools to express endless complexity is probably a good idea.
It’s the main reason I’m looking at switching to Go for these kinds of apps. Python should have a working solution as part of the standard library.