But it would be a mistake to consider Python anything but luxury glue no matter how much you've used it for production code, it isn't and never will be a bullet proof language, there are just too many ways in which the runtime can surprise you and the long term maintainability of any Python codebase is always going to be questionable, in part because you will most likely have dependencies on stuff that will silently disappear or change out from under you while you're not watching.
I've been writing Python code pretty much since it was first released and there isn't a single piece of code that I ever put together that worked longer than a few years out of the box without some breaking change. This as opposed to just about every other language that I've used, which I find very frustrating because Python could be just about perfect. And I'm still sore about significant whitespace ;)
The best practice, which prevents this issue, is to use envs, (as well as pinning your dependencies for any given project in a committable artifact).
(Seems like a lot of people are using system Python, which isn't really recommended.)
The whole idea that you need a multitude of environments to support applications written in the same interpreted language is where it breaks, that should not have been necessary if backwards compatibility had not been an issue.
I really like the language, but all the tooling is seriously broken.
Fwiw what I've settled on that seems the most stable is to use pyenv as the "outer layer", as it shims the python interpreter along with any venvs so you don't get conflicts / heisen-incompatibility. Lets you use anaconda envs as children as well. The real trick, I think, is to pick one system as the canonical master env controller and don't deviate.
The code typesetting is for the humans not the machines.
That is a lot worse than formatting squabbles, especially for a glue language where you are expected to be able to copy snippets for short scripts all the time.
The libraries are very powerful, but a lot of them are hacks. Numpy and Pandas totally rely on magic and overloading the array indexing operator. You can't express a problem the natural way or it will be slow, you have to think the numpy way. I find it especially confusing if you create expressions with numpy arrays. Am I operating on them element wise, or creating a "cross product", or am I creating some kind of magic indexing object? Matplotlib is also annoying, there are so many ways to do things and half of it is object oriented, while half of it uses global state.
One thing I like about Python are the web frameworks (Django, Flask). Async is also good, although it took almost 10 years for vanilla Python to catch up with what Twisted already had.
About code breaking I also have the opposite experience. I wrote a little Gtk app in the late 2000s and it worked with little or no changes for many Python and Gtk versions, thanks to the dynamism of Python. That would be completely impossible with a compiled language.
I do think that "The libraries are very powerful, but a lot of them are hacks. Numpy and Pandas totally rely on magic and overloading the array indexing operator. You can't express a problem the natural way or it will be slow, you have to think the numpy way. I find it especially confusing if you create expressions with numpy arrays. Am I operating on them element wise, or creating a "cross product", or am I creating some kind of magic indexing object? Matplotlib is also annoying, there are so many ways to do things and half of it is object oriented, while half of it uses global state." is an illustration of my point: the language itself isn't powerful enough to do the job so you rely on a lot of libraries written in different languages to glue it all together.
An 'elegant' language would provide a way to do so without all of these leaky abstractions.
To me Clojure is such a language, but it doesn't nearly have the kind of ease of use that Python has.
The language is 100% capable. Matplotlib's API is horrible and confusing because one of their design goals was/is to be similar to matlab (that's where the "mat" in it's name comes from) to allow people who are comfortable with matlab to switch more easily.
Matlab's plotting facilities are a mess of global state, so matplotlib has copied it.
> An 'elegant' language would provide a way to do so without all of these leaky abstractions.
It would have to do something else, first: Exist.
In 10+ years of programming, I've yet to ever see a implementation of a complex abstraction that was comprehensive and complete enough that I didn't find a corner case requiring me to reach through it and deal with platform specific something-or-other.
I think I like Python, because coming from C, a lot of things that are tedious there are effortless in Python (Strings! Lists and dicts, libraries, and so on.)
That's why each and every number crunching problem will eventually make use of the various escape hatches to call libraries written in a language that is performant.
As for strings: BASIC also had strings. That doesn't mean that having strings (or even dicts) is what makes a language elegant.
The problem really is that there are only so many sweet spots for programming languages and usually those come with limitations with respect to the domain you want to use them for. Pick any two: expressive, fast, easy to use.
For Java 8 especially, the later reason is particularly amusing, as Oracle's extended support is now slated to go to 2030 (16yrs after release, for comparison Py2.7 got 10yrs), but Java 21, the next Java LTS that should release next year, will be on Oracle's standard 8 year extended support cycle, and thus extended support only goes til 2031. So why would anyone decide, much less how would one justify to a corporate overlord, to spend all the time and resources to refactor their code, upgrade libraries (assuming the libraries themselves upgrade), update build systems, perform extensive regression testing, and everything else, just for a version that would be EOL one year after what they just upgraded from?
The longer you delay upgrades, the bigger the delta, the more work it will be to update. Instead of doing two medium sized updates, one today and another one in 2030, you'll be doing a huge one in 2030. That might be a trade off you might be willing to make today, but you might regret it in 2029 when you're halfway through a multiyear migration project where all feature work is on hold.
At least not until the day they suddenly didn’t.
FWIW I found it nearly useless - whereas biting the bullet and refactoring it so that it could be unit tested - even just a few tests - made a world of difference.
That's been happening more and more recently to me. Python 2 really was lax about letting you mix types and get shit done fast, but Python 3 is a different beast entirely. Really opinionated.
Oftentimes there's... Bodges and hacks that made shit work that I never documented.
The actual migration should you choose to do it was almost trivial. The official conversion script did most if not all the work. The changes were all cosmetic, like "print 42" changing to "print(42)".
I'd say the uproar was about the minorness itself. The syntax had these tiny but otherwise incompatible changes, and for many people, for no good reason. Fo example it was deemed that, as in the example above, print shall not be a statement anymore, but a function instead. Why? Unclear. Meanwhile, Python 3 offered few concrete improvements to many users
So I think the 2->3 moan, of which I was a party, was about that: minor, unnecessary changes that introduced little to no benefit, and yet backwards-incompatible.
If that were it, it'd have been over a lot sooner. For some packages, bytes vs Unicode strings was bad. For many more, layers of dependencies were an impediment. The trivial stuff wasn't the problem.
But for example a big stumbling block was the scientific programming community, from which I also stem. There were no major syntactical reasons there and yet people were up in arms, for the reasons I describe above.
Most people I know migrated only when python2 literally wouldnt work for them anymore, like they needed a feature of a library only released for python3.