Software is never alive or dead. And python2 can certainly be found in the wild. Just yesterday I tried to use buildroot to build an image for my rock64 board. The build failed because a python2 script was executed by a python 3 interpreter.
Are there any companies out there that might sell supported updates to Python 2 going forward? Seems like a decent business idea considering how much Python 2 is still in the wild.
Seems like that would quickly fragment unless the ecosystem consolidates around one particular vendor or all such vendors consolidate on a standard fork.
There will be patches. Ubuntu 18.04 LTS shipped with 2.7 and is supported until 2023. RHEL 7 shipped with 2.7 and is supported until 2024. What will be interesting to see is if there will be a "standard" fork that everybody pulls patches from, or if every vendor patches himself ...
Because python2 isn't just a language that dissolves away once the program has been written. It's also a thick interpreter and runtime system that will slowly rot away without maintenance.
It's yet to be seen how this runtime will be maintained in the future. Of course, given the enormous usage of python2 it's clear that it will be possible to use it far into the future. But it's really an unprecedented situation where an enormous software platform is abandoned by its developers. If this were a commercial product, it would filter through the long tail of software graveyards like Oracle and Computer Associates. I imagine the main annoyances in the future python2 landscape will be vendor fragmentation and diverging implementations.
MacOS just killed anything with only a 32bit build. Who knows, in 10 years they might do the same to 64bit. Even on one of the most conservative platforms ever, Windows, old programs will often struggle to run. And now that the network is also essential, there are a bunch of other sources of rot: can the platform speak TLS 1.99 with randogenerated certitokens? Will it understand http/5 and blockchained dns?
You could always configure that software to run with a local Python2 by changing the way it is called. Then you can move on to Python3 for other stuff. No need to get left behind.
Actually Latin is still being developed, as official language for Vatican documents and they have language experts to update the dictionary for modern terms to keep the language updated.
To join in the other comments here: because it's not safe to do so automatically. There are semantic changes to the language that do not have automate-able solutions. E.g. how strings/unicode/bytes work, to name just one.
They exist, but Python, being a dynamic typed language, at least by default, runs a higher risk in automated conversions. Just because it compiles after conversion doesn’t mean it isn’t broken.
Unless the code base has a very very good set of unit tests, which is unlikely in practice, it is very risky to do automated conversions.
Whereas the same situation with Java, Go, Rust etc would be slightly better. Sure you would still have bugs but lower probability.
Does that mean that random things that rebuild or restart and require "pip install requests" before they start up or whatever will just gleefully break on Jan 2021?
I'm guessing you'll get a warning when installing or updating pip on Python 2.7. I know for Python 3.4, pip has been showing a deprecation warning whenever it's installed for a while now. I assume they'll do the same for 2.7.
So, I suppose the answer to your question is yes--if you blindly update pip and/or you don't heed those warnings and pin your pip version accordingly.
Edit: I was curious, so I installed the latest Python 2.7 and pip. `pip install` (or any other pip command) shows a deprecation warning with info about dropping support for Python 2.7 every time you run it.
I didn't get the point of this at first (and still kinda don't). I think the most useful thing might be this link: https://python-release-cycle.glitch.me/. It's a nice visual representation of Python version lifetimes, which is useful when deciding which versions you want to support. I wish they'd put something like that on python.org.
What motivated the Python devs to abandon backwards compatibility with Python 3? I don't see any major departures or revolutionary new features transitioning from 2 to 3. While there's certainly upgrades (e.g. strings), there's enough small changes that upgrading to 3 is rarely a pleasant experience.
What that article casually ignores is the fact that there could have been a Python 2 fix (as Python 3) that took the approach of fixing encoding to utf8 only. If that was the only thing Python 3 vs 2 was breaking, life could have been so much better.
The truth no one wants to hear is that Python2 did Unicode right (or as well as could be expected), while Python3 is a train wreck, even if you just stick to LANG=C and ASCII.
The surrogate escape issue was fixed in 3.7 and you shouldn't use LANG=C as a locale, you should use LANG=utf-8. Python doesn't have bad unicode handling, the system does when you set LANG=C.
And no, for people who actually have to use unicode, python2 didn't do unicode anything like "right". Python2 did unicode "right" for the people with LANG=C and ASCII. Those people are generally wrong.
Even pallets notes
>Misconfigured environments can currently cause a wide range of Unicode problems
The keyword there is misconfigured. Your system is misconfigured. Fix it (by making your locale correct). Then the problems go away.
Lang=C is broken if you have non-ascii unicode filenames (or many other things, but those are the most obvious). That's not pythons fault, it's your bad encoding.
Python trusts the system, and the system lies. It's your fault for lying to python. Configure your system correctly, don't lie to your tools and then blame them.
Lang=C is the realm of English only 70s crap programs. You shouldn't use it. Use a modern encoding that supports modern characters.
POSIX filenames are a series of bytes. That's all you get, and it makes things strikingly simple.
Trying to wedge Unicode in at this level is a recipe for disaster, and after all these years, Python3 still doesn't have a reliable, coherent story on this.
> That is, just show me the bytes, escaped as needed
this isn't actually how python 2 works either. `print("Ń̸̗̮̯͇͈͇̑͒o̸̧̭̯̖̾̐̔̈́̋̈́̈́͘)` will print the same string, since my machine's locale is utf-8. So python2 does the same thing as 3 with regard to machine encoding.
In addition, the whole idea that a system must have a privileged locale is silly in our connected world. Even assuming a single process (which can be talking to endpoints in many countries) should be locked to a specific locale is nonsense.
The beauty of LANG=C is that it's the only true lingua franca of modern computing. It's a place where all software and programmers can "meet" without privileging any particular locale.
We have 'gettext' and friends for speaking to humans in particular locales. Embedding i18n into core system design just doesn't work.
> Even assuming a single process (which can be talking to endpoints in many countries) should be locked to a specific locale is nonsense.
This doesn't matter. I'm not sure why you think this matters or what problems will be caused, but a server using a unicode locale (C.utf8 or en.utf8) doesn't localize things for those clients, it just is able to not crash when printing their usernames to log files.
> it just is able to not crash when printing their usernames to log files
The usernames could be from a variety of locales. If showing them in that form is seen as valuable, they'll each have to be decoded in their appropriate locale. Using LANG=C doesn't prevent this, it encourages it.
Beyond that, as you point out, Unicode provides lots of new opportunities for crashes. Indeed, one of my favorite ways to crash software (software almost invariably running under a "proper" locale) is to feed it a string of (non-ASCII) Unicode. Boom.
No matter the approach, you must code for correctness and deal with all input. For Unicode, you must always allow for decoding failure.
> The usernames could be from a variety of locales. If showing them in that form is seen as valuable, they'll each have to be decoded in their appropriate locale.
You realize that locales and encodings are different right? En.utf8, c.utf8, and fr.utf8 are all different locales, but are all utf-8 encoded. They'll all work correctly when printed on a machine with any other utf8 locale. The differences arise in things like sort order and regex, where c.utf-8 might be best for a server if you want C or ASCII like functionality.
> Using LANG=C doesn't prevent this, it encourages it.
Well no, because you don't know what encoding each person is using. Either you guess which is error prone, or you have to control the other endpoint so that they include the encoding. But if you control the client, just use utf-8.
Pretty much no software does what you suggest. Go and rust, for example, go further and entirely ignore the system locale and just always use utf-8 for everything. People don't complain.
I am not a "unicode purity fetishists" and python 3 has been a compelling upgrade for me for the past 3 years. I have not written single line of python 2 code since 2 years ago. So your statement that it is not compelling for anyone is wrong. Maybe some people are python 2 fetishists? I have upgraded multiple python 2 codebases to 3 and I am not understanding what people are whining about, it is not rocket science.
This is something people are getting paid to do; maintain their codebase and keep it up-to-date.
Because no one could ever be justified in moving to Python 3 for AsyncIO, f-strings, ordered dictionaries, assignment expressions, pathlib, new features in shutil/tempfile/subprocess/etc, along with massive improvements to memory consumption, runtime performance, and overall stablility?
Until 3.8 py3 was slower than py2 in practically all benchmarks, and 3.8 is a marginal improvement at best. So I’m slapping a massive <citation needed> on your “massive” performance improvements
We switched a service from 2.7 to 3.5 and saw an immediate 45% reduction in memory usage and 20% reduction in runtime. That's massive IMO. We saw further (but smaller) performances benefits upgrading to 3.6, again when upgrading to 3.7, and expect to see even more with 3.8.
People can and have been fine without those things for a long time. Many of them could have been added to Python2 without any trouble. And yet we still have a GIL.
None of our projects had any trouble, rarely is an overstatement. Only if the project was huge and dealt heavily with string/bytes was it a problem. Everything else could be fixed mechanically.
Python 2 isn't dead. What they really mean is: "See all those countless developer-hours spent into adding features, fixing bugs, patching vulnerabilities for free in a language you use every day to make boatloads of money without us ever asking anything in return? Well we won't do it anymore. For free, at least."
> If enough people say it’s dead and believe it in their heart, it makes it true.
except for COBOL, which has the Schrodingers' property of having been (called) dead for 40+ years, but also somehow powering the world and its' infrastructure.
Who besides "government" and related spin-offs such as DoD contractors use COBOL?
Does "subsidized zombification" count for a programming language being otherwise dead?
Side Note: 20 years ago a SciFi book introduced me to the idea of "Software Archaeology". These days, such a term is slowly gaining traction as a job description. I've had to professionally dabble into this myself from time to time.
$ /usr/bin/python2
WARNING: Python 2.7 is not recommended.
This version is included in macOS for compatibility with legacy software.
Future versions of macOS will not include Python 2.7.
Instead, it is recommended that you transition to using 'python3' from within Terminal.
I agree, yet I think it's for the best. Apple has not been a motivated steward of the Mac Unix layer, so it's best for them to get out of the business entirely, and make space for the community to converge on a standard package manager.
Was it really though? Speaking as somebody who considered learning Python several times over the course of a decade I was seriously put off by the protracted uncertainty around 2 vs 3.
There was a long period - years long - where everything that "mattered" seemed to be supported by and available for Python 2 and there was a ton of FUD, along with genuine issues, about incompatibilities with Python 3. When I asked which version I should learn I felt like I couldn't get a straight answer.
I never had a strong need to learn Python: I just thought it might be a fun and useful thing to do, because people seemed to like the language. But I wasn't interested in investing time in something that might wind up unsupported in a few years, and because I didn't have any serious need for it, it wasn't worth digging through the morass of misinformation to get to the truth.
As an outsider it was extremely unclear to me which version of Python would be actively supported for the long term. 20:20 hindsight says 3 was the future but - and maybe this is just bad mar-comms - back then it seemed like there was a reasonable chance it was either going to be a dead end or exist perpetually in this weird no-mans-land of "not quite ready for prime time".
Had I learned it there's a good chance I probably would have used it for something more serious by now. But I didn't, and so I have to disagree: it was done extremely poorly.
I don't really understand why there has been so much hemming and hawing about Python 2 vs Python 3 with regard to the language itself. If you already know a few programming languages (rather than being a neophyte coder), Python 2 and Python 3 are so similar that their major differences can be summed up in one or two pages of code examples. Sure, they're not backwards compatible, but if you know one, you'll have no trouble being able to at least read and understand the other without much effort. The bigger issue is the ecosystem taking the time to catch up. Also, I'm not sure that Python 3 is really much of an improvement over 2 rather than just different.
Python tried to pull a Perl 6 and failed. Python 3 was done as a flag day, a big breaking change you need to switch over to. Originally Python 3 and Python 2 lacked features that would make it possible to write code that is compatible with both versions (like `u"foo"` syntax). Slowly they added things to Python 2 and 3 to make it easier to slowly transition.
But it was still full of unnecessary breaking changes.
- The `print()` function is nice, but they could have left in the `print` statement for a transitional (deprecation) period. Or left the `print` statement in, and advise against its use.
- A lot of the incompatibilities are just stdlib modules being moved around unnecessarily. They could have made both import paths work for a transitional (deprecation) period. Or let the old paths continue to work forever, and just document usage of the new paths.
- All the new features in Python 3 (async, nice helper functions, etc.) are compatible with Python 2. They could have added them to Python 2.
The only true breaking change was unicode literal strings. But again, that could be handled with a slow transitional (deprecation) period. The Python 2 stdlib could have been made compatible with both types of strings (as nearly all third-party libraries have). And users could have been told to `from __future__ import unicode_literals` for a transitional (deprecation) period, to ensure their code is compatible before it becomes the default.
Basically Python 3 could have been a single hard breaking change (unicode literal strings), with a smooth transition. Instead they decided to make Python 2 and 3 diverge from each other, making it harder to do the transition.
> The `print()` function is nice, but they could have left in the `print` statement for a transitional (deprecation) period. Or left the `print` statement in, and advise against its use.
They did, it's from __future__ import print_function. python2.7 was, essentially, the transitional deprecation period you mention, and it lasted a decade.
> A lot of the incompatibilities are just stdlib modules being moved around unnecessarily.
six.moves
> - All the new features in Python 3 (async, nice helper functions, etc.) are compatible with Python 2. They could have added them to Python 2.
This assumes a level of similarity in the py2 and py3 codebases that isn't true in practice. There are different bytecodes and 3.0 only optimizations. Backporting some of these is possible, but not a reasonable burden.
>The Python 2 stdlib could have been made compatible with both types of strings (as nearly all third-party libraries have).
I don't know what you're working with, but most third party libs aren't compatible with both types of strings. They're compatible with str or bytes, but not both except in rare and usually wrong cases.
Importing unicode literals only sometimes solves the issues, and often times introduces different problems.
> - The `print()` function is nice, but they could have left in the `print` statement for a transitional (deprecation) period. Or left the `print` statement in, and advise against its use.
The print statement dates to antiquity (cf. BASIC) and could certainly coexist with the print() function. It was a nice and friendly piece of syntax whose removal was entirely unnecessary.
Now that Python is free of GVR, perhaps we can restore the print statement to its rightful place in the language! ;D
The plan was for people to write Python 2 and generate Python 3.[1] What eventually worked was making it possible to have a single code base. Imagine if that had been possible all along.
At first glance, you're right. But if you take a closer look, from a purely pragmatic perspective, there are now at least two coexisting ecosystems in two different languages, peacefully sailing along.
Python 2/3 is in this kind of weird twilight zones that the two versions are far away enough that you can't have a smooth transition like in e.g. C++, Java, Rust, Go, etc., but still close enough that there is not a clear cut like in Perl5/Raku. So for a few years, one had to juggle with some of the libs that were 2-and-3 compatible, some that were 2-only, and the others that were 3-only.
C++ et al. let your code evolve Theseus ship-like; Perl makes you build a new ship; and Python tells you that your ship should be OK if you repaint that thing, change a bit of that one, oh, and by the way, you'll have to check very carefully your bunkers, because the boilers will explode if every coal nut is not Unicode-compatible.
I remember when in late 2009 I wanted to pick up Python and was conflicted whether I should learn Python 3 or 2 - obviously I wanted to try the new and shiny, but was put off by the lack of compatible libraries at the time.
Eventually settled for none. I didn't know that at the time, but later it proved to be a career defining moment.
Similar thing happened with me starting around the same time (Python 3k I think they were calling it in 2007/2008). Every few years I’d look to Python again and the same split was happening in the ecosystem. It always put me off.
Definitely changed the course of my programming career.
What did you end up learning instead? Learning python (2, then 3) changed the course of my career for the better, starting with web development, then machine learning. I’m doing mostly javascript these days but still use python a lot for web scraping, business process automation, and machine learning. It’s pretty versatile.
I spent a lot of time with Ruby as a younger developer along with JavaScript, but these days spend most of my time in Go. Some Swift and Rust depending on what I’m working on.
The problem is that it wasn't really a transition. Rather, Python3 is a new language that is deceptively similar to--and crucially, not compatible with--Python2.
Nothing really wrong with that, but it should have been called "Cobra" or something. And the weird jihad for killing off Python2 should never have happened. If everyone moved to Cobra on their own, great. But there should have been no beatings.
Call it what you will but if python 1 and 2 were still supported, I'd have customers demanding I support them indefinitely.
This way there's no expectation, I get to wash my hands of it all. And without an awkward "I'm moving to Viper now chaps". It's a system update paradigm that people understand.
That works when you have one or two customers per codebase. It's still not great. Context switching Python 2 and 3 is getting increasingly hard as 3 diverges.
But when you have a few dozen customers on a single product, supporting edge-cases that require core forks becomes incredibly hard. Especially when you need modern Python features.
We tried it. It doubled TTL for simple patches, and meant the Py2 version fell behind in terms of gross features. It was expensive for us, worse for the customer, so we dropped it and moved to a unified core. We had one customer threaten to leave but they didn't. Somebody in their IT department rubbed two brain cells together and agreed with our assessment.
A customer might leave over this sort of behaviour, but again this worked out to be more cost effective, so we would probably do the same when Python 3 is EOL. Wheel keeps turning.
python2: just works. If you install python2 you get the same stable version everywhere.
python3: Oh, sorry, you used a feature that was added in 3.x and this system has 3.(x-1) so now you get SyntaxErrors, or worse, random runtime exceptions.
If you can target a container, buildpack or a specific platform python3 is fine, but it's been terrible for developers and users since day one. At least, it's been terrible for me, which is why I still have a pile of stuff to port to python3.
It's fine for something like go or rust to add new features in a dot release, where you just need to upgrade your development hosts. Besides, if it compiles it will work, no surprises later.
But python3 adds new features in 3.5, 3.6, 3.7 and then immediately breaks all new code on older systems.
Used f-strings? Now your code is broken on 3.5.
A new feature used the walrus operator? Now your code is broken on any system that doesn't have 3.8 yet.
> python2: just works. If you install python2 you get the same stable version everywhere.
> python3: Oh, sorry, you used a feature that was added in 3.x and this system has 3.(x-1) so now you get SyntaxErrors, or worse, random runtime exceptions.
Maybe you were used to Python 2.7 only as "Python 2", but when it was in active development, major 2.x releases had the exact same thing. I had some serious troubles when the latest version of RHEL was on 2.4 while the rest of the world had 2.6 with very large changes. There were all kinds gross hacks just to make things work on an older, common version.
Are you talking about making Python 2.6 code work on Python 2.4, or about making Python 2.4 code work on Python 2.6? The parent is talking about the latter for Python 3 (edit: looks like I misunderstood, never mind), but you seem to be talking about the former. They're not the same thing.
Python doesn't break backwards compatibility like that. Code written against 3.0 will still work perfectly fine on 3.8; likewise for 2.0 code running against 2.7.
Parent seemed to be talking about the reverse: going backwards, and implying that 2 didn't have major new features, even though it very much did.
Are you talking about PEP-0492? It was added in 3.5.2 with deprecation of previous behavior in 3.7, release dates of those are separated by exactly 2 years, with deprecation warnings in 3.6.
Python3.8 is breaking things left and right because people are using the walrus operator and then realizing that users don't actually have python3.8 installed.
I think you're making a very similar point to the comment you're replying to --- that "dead" really means stability; no more worrying about changes that make things stop working.
Personally, as a developer who has been working on software for a few decades, I've gotten increasingly irritated with the growing churn of platforms today and the astonishing waste of time for everyone who has to deal with it. It's hard to hit a moving target or build on a shaky foundation, but that's what the state of software seems to be today. Instead of platforms approaching stability and spending time on the actual problems at hand, countless developer hours are wasting solving problems created by others "pulling the rug out from under them".
I guess the younger generation of developers just hasn't felt enough of that pain yet, or they're overeager to try new things without thinking of the consequences. I've always taken the conservative approach and as a result some of the software I've written has needed little if any new attention in decades. Some utilities I wrote 25 years ago (not in Python, obviously), I still use regularly. "It's not the tool, it's how you use it."
It’s a combination of the tool and how you use it. And the environments that tools run in today are sometimes dramatically different than they were 25 years ago. As constraints and limitations change due to technological progress, economics, etc., so too does our software. I don’t see anything wrong with that. Nor do I see anything wrong with tools that adopt a tenet of not changing, both have value.
25 years is one thing. 1 year is another. There has to be a middle ground. 10 years doesn’t seem too bad. And Python 2.7 has shown that to be remarkably reasonable.
I think you're making a very similar point to the comment you're replying to --- that "dead" really means stability; no more worrying about changes that make things stop working.
But you're missing the same point that the parent commenter is missing - stability only came because Python 2 has been sitting at 2.7 for so long.
And you're also missing the point that you can have the same stability by sticking to 3.6 or 3.7 or 3.8 or whatever your fancy is. If you stick with 3.7, I assure you that 3.7 will remain exactly the same and no one is going to pull your rug out from under you. Just don't upgrade.
I think it will eventually settle down once people have tried all the ideas and the needs of programmers have stabilized. Kind of like how bolt threads were eventually standardized after decades of everyone doing their own thing. First comes the end of progress, then comes stability. We already have that with some computer things like basic Linux commands or HTML.
You can always stop now if you want. Download the versions of everything you need and never change. But you'll miss out on the cool new hotness that you're wanting everyone else to miss out on if they stop changing too.
I would believe you if it wasn't for the fact that most things being invented in software today are new. The industry keeps reinventing things that people did in the 60's without even doing it properly.
Why doesn't any recent programming languages implement a proper condition system for example? It's not like working implementations hasn't been around for decades.
This industry has a severe case of inability to learn from history so I strongly doubt we'll see things settle down in the near future.
Also, if you write library code, you can, and should probably have CI running against Python 3.0, this way at least your code doesn't break when used against a newer version.
I got on python-dev recently and tried to make the case that breaking changes should be delayed to a X.0 release. It didn’t get very far, they seemed to determined to keep the current low predictability system.
The response was they don’t have enough manpower. The though ignoring deprecated stuff a few releases doesn’t sound particularly hard. I suspect Guido just likes it that way.
Btw, almost no one supports forward compatibility.
They've had small breaking changes on many minor releases.
The difference is the scope of the breakage. Python 3.0 broke every project. Python 4.0 certainly wouldn't, they are very timid now. In comparison, these breaks are tiny in scope.
Yep, the latter, I'd much rather a deterministic failure. Or if you're using something like Poetry to package your code, you can specify supported versions and then users of your code will be informed if they lack that Python.
But then if you're trying to write portable Python 3 code without any need for the end user to be pyenv-ing stuff, you probably don't want to be writing 3.8 - off the top of my head, Ansible, for example, targets Python 3.5 for this reason.
I'm not defending this btw, modern Python development is painful, and I taught myself to code in Python, so it hurts to see my first love so.
I guess it would be nice if Python came up with something like Java's source/target which errors if you're using incompatible features.
Yeah, I think webdevs and univ students are overly vocal on the internet. They can usually enjoy the new tech, because that's how the industry makes $$$. But there are other parts of the world that don't move that fast. All those "migrate to Python 3" should changed to "develop new projects in Python 3" instead.
I came across Tauthon [0] a while back, it seems quite active. I have a codebase that has proven difficult to port, so this is the backup plan.. "Tauthon is a backwards-compatible fork of the Python 2.7.18 interpreter with new syntax, builtins, and libraries backported from Python 3.x. [...]"
Regardless of Python 2 vs 3, what is sad is that every new language, be it Go, Rust, Swift, Dart, Nim whatever is dividing whatever set of ‘good, smart, and creative’ engineers we have into smaller group each implementing their own sorting algorithm in their own language. Just to be clear, I am not counting myself among them. I am talking about those who design languages, write runtimes, JITs, stdlibs whatever - people much smarter than us. They do this in their free time!
I am surprised that even 1,000+ languages (at least 50+ mainstream) haven’t satisfied all the wishes and itches. May be that is humanities curse! Creative people constantly want to create a new language and redesign everything while bigger and better problems remain unsolved.
Python 2 vs 3 just seems like yet another thing that breaks up the creative talent pool to waste time solving the same problem in two ways.
LLVM is the first thing I have seen that removes at least some of this duplication. But I hear even Rust is looking at alternate backend! Go doesn’t even use LLVM, all for good reasons I am sure.
Funny. I was actually hoping that with python2 officially dying, after more than ten years there's finally a chance to re-join at least these two specific camps.
Now that managers will have to have good reasons to keep maintaining the language on their own or make the switch, I was hoping to see a more focused community with less "import * from six" overhead.
Are they really divided? Maybe if people only used one language. I would suspect that almost any Rust, Go, Swift, Dart, and Nim developer today is proficient in one, probably two other languages, at the least. I doubt that even 10% of "Rust programmers" are employed to write Rust full time.
What I might agree with is that interoperability is something that should be considered more going forward. I'm unsure about some of them, but Rust focuses a lot on interoperability via FFI, Go's FFI story is bad, as far as I know, Nim's is decent, and I don't knwo about Dart or Swift.
The top languages are all virtually identical. There's so little difference between, say, Java and Python, despite there being so much difference. So maybe there are 50 "serious" languages, but they all fall into a few buckets. There's less meaningful diversity than it seems, I think.
Your point about interoperability is probably a better expression about what I had in mind. Whenever there is a new advance in algorithms, at least all languages should benefit from the “reference implementation”, be it C-FFI (the current story - write in C first and everyone wraps) or something like WebAssembly. Then when a fancier/more idiomatic one is available, use that. Current story with the C library path is so hard to use in practice.
I do not really understand your concern. What you say "duplication" is not harmful in any way, but a path towards progress.
A new programming language is like a new material. You can build chairs and tables in wood. But when a new metal is introduced, is it worth to "duplicate" the work and build chairs in the new material? Maybe, who knows. You may end up with a chair that has surprising new properties, impossible to have in wood. Or maybe it is worse in any measurable way, but some people may still prefer it for some reason. Would you complain to the discoverer of a new material that they should not build chairs in that material, because chairs are already solved (by using wood), and they are just losing time by reinventing the wheel?
Technology advances by the continued reinvention of the wheel. Rewriting old algorithms in new languages is a beautiful part of that.
> Python 2 vs 3 just seems like yet another thing that breaks up the creative talent pool to waste time solving the same problem in two ways.
Most people who actually used Python 2 have zero issue using Python 3. And most people coming into the Python ecosystem now only ever experience Python 3.
The people whining about Python 2 have legacy codebases. And, they have a right to whine, but Python 2 at least will continue to exist. Look at Visual Basic 6 codebases by contrast--more and more of those break with every Windows release.
This is also way different that say the ObjC to Swift transition. Apple simply said "Move, or don't. And if you don't we won't ship your app." And the community moved.
> Regardless of Python 2 vs 3, what is sad is that every new language, be it Go, Rust, Swift, Dart, Nim whatever is dividing whatever set of ‘good, smart, and creative’ engineers we have into smaller group each implementing their own sorting algorithm in their own language.
Sorta, but the whole point of a language is to have a strength that outweighs the negatives of creating it.
If I go through the Tiobe index and look at relatively new languages (there aren't that many in the top--Python, Ruby, and Javascript hardly count as new):
Swift is ObjC moved forward. That one was never going away.
Go is for concise networky client/server thingys. Okay. That's better than most other languages and has some large codebase improvements.
Rust is the only non-GC language in the pile and it aims to be a better C/replace C++--an arena that has been absolutely stagnant for 30+ years.
<dons asbestos suit>
Dart ... okay, you got me. I have no idea "Why Dart?". Every time I interact with it it seems to look like a crappier Clojure with Google foisting it on the world. When your function closings look like this:
);
},
),
);
}
You have Lisp-envy. I often wonder if this is just some team inside Google going: "Android Studio is absolutely terrible, anything is better, but we can't budge the glacier. We need to route around the brain damage."
D was meant to be a better C--but it took far too long to get a useful non-GC subset so never found its niche.
Scala--Meant to bring Haskelly goodness to the Java ecosystem. In my opinion, overreached, never really achieved its goals and now is competing against better languages. It took FOREVER until the whole Actor system worked decently in Scala, for example. To be fair, it also appeared in like 2000(?) back when the Java language ecosystem was basically crickets chirping. The JVM has improved a lot since then and made language development a lot better.
Kotlin--presumably in the right place at the right time. A modern Java before modern Java. And appeared at the point where Google needs to make sure to have an escape hatch against Oracle if required.
Groovy--Possibly the worst language to have any traction. However, most people's interactions with Groovy come about when they have to fix something broken in the absolutely horrible Android Studio build system. Friends I trust say that Groovy isn't really that bad (but not that compelling) but that, yeah, the Android Studio Build system is a horrible exemplar.
I was planning to host and maintain a fork of Python 2.7 in perpetuity (I was gonna call it "Bladders" ;-)
It turns out that Pypy will have Python 2 support. I don't know the details but it sounds like you'll be able to run py2 code using pypy (not pypy3) for N more years.
PHP is still used by 78.2% of the internet according to some sources [1]. The death of any language or version is always greatly exaggerated. Maybe new projects aren’t being spun up with it, but many old projects never die and need ongoing maintenance. Until very recently the most recent project I was working on used python2.
You say "php is still used" as if php was dying, it's never been stronger. The language is getting much better every year along the new versions, and the ecosystem is getting better.
175 comments
[ 3.6 ms ] story [ 218 ms ] threadDo you want to come back to Python 3, bouncy bouncy?
Edit: this comment is meant to be funny but serious, it's not going anywhere, I've seen older tech that's still going strong in the "enterprise".
It's yet to be seen how this runtime will be maintained in the future. Of course, given the enormous usage of python2 it's clear that it will be possible to use it far into the future. But it's really an unprecedented situation where an enormous software platform is abandoned by its developers. If this were a commercial product, it would filter through the long tail of software graveyards like Oracle and Computer Associates. I imagine the main annoyances in the future python2 landscape will be vendor fragmentation and diverging implementations.
I've never understood where this mentality comes from. I have programs 30+ years old, and still use them because they work perfectly fine.
That’s “where this mentality comes from”.
Telephono mobili Android decurrit
Unless the code base has a very very good set of unit tests, which is unlikely in practice, it is very risky to do automated conversions.
Whereas the same situation with Java, Go, Rust etc would be slightly better. Sure you would still have bugs but lower probability.
So, I suppose the answer to your question is yes--if you blindly update pip and/or you don't heed those warnings and pin your pip version accordingly.
Edit: I was curious, so I installed the latest Python 2.7 and pip. `pip install` (or any other pip command) shows a deprecation warning with info about dropping support for Python 2.7 every time you run it.
The truth is that Python3, as a new language incompatible with Python2, was a mistake. I'm sure it was well intended, but here we are.
https://click.palletsprojects.com/en/7.x/python3/
and here, have a nice sandwich of this:
https://stackoverflow.com/questions/57652720/runtimeerror-cl...
or this bullshit:
https://bugzilla.redhat.com/show_bug.cgi?id=1404918
The truth no one wants to hear is that Python2 did Unicode right (or as well as could be expected), while Python3 is a train wreck, even if you just stick to LANG=C and ASCII.
And no, for people who actually have to use unicode, python2 didn't do unicode anything like "right". Python2 did unicode "right" for the people with LANG=C and ASCII. Those people are generally wrong.
Even pallets notes
>Misconfigured environments can currently cause a wide range of Unicode problems
The keyword there is misconfigured. Your system is misconfigured. Fix it (by making your locale correct). Then the problems go away.
And no, LANG=C isn't wrong. Your software has one job, to at least be correct for LANG=C. If it can't do that, it sucks.
Python trusts the system, and the system lies. It's your fault for lying to python. Configure your system correctly, don't lie to your tools and then blame them.
Lang=C is the realm of English only 70s crap programs. You shouldn't use it. Use a modern encoding that supports modern characters.
Trying to wedge Unicode in at this level is a recipe for disaster, and after all these years, Python3 still doesn't have a reliable, coherent story on this.
But not windows, or a number of filesystems. Hell the vast majority of the time posix filenames are ASCII, and therefore utf8 compatible.
The rare cases where they aren't break all kinds of other tools because...
> Trying to wedge Unicode in at this level is a recipe for disaster,
Blame every terminal emulator and os in common use. They all display filenames in unicode. So pythons in good company here.
Since you have to display filenames, they need an encoding.
Ń̸̗̮̯͇͈͇̑͒o̸̧̭̯̖̾̐̔̈́̋̈́̈́͘t̵̖̹͙̟͑̈́̎̀͝ͅ ̴̡͒͌̋̾͆̒̎ȧ̴̬̰̪̮̩͉̐̈́̋̇̀̊̕ ̷̫͑́͑̕͠f̸̬̥̼̣̙͎͍͙̤͗͆ͅā̸̛̼̱̠̯͖̫͓͙͒̔͂̅͜͝ͅń̴̨̨̨̦̺̺͗͗̉̎̓̀͘͘͠ ̵̢̖̞͍̻̮͈̘͎̹̉̇̈͐̍́̂̂̀̂o̴̳͙̿͆͝f̵̮̙̞̰͖͉̰̞͕͑̍̀̄̎̍͜ ̵̛̗̙͓̰̹͇̍̒̋͆ͅU̶̧̯͇̰̞̮͋n̵͉̰̰̳̗͎̂͑̉͛̏͛̌i̵̢̢̪͂́̽̀͝͠c̴̢͇͙̙̲̯̫͈̪̀̌̓̂͗̚͜͠ơ̷̬͖̙̯͇̻̱͕͐̎d̶̛̤͉̻͆̋͋̂̀e̵̦̺̹̅͆̀͛̎̎̅.̸̡̟̰͙̮̱͍̼̾͊̑̅͊̚͝
this isn't actually how python 2 works either. `print("Ń̸̗̮̯͇͈͇̑͒o̸̧̭̯̖̾̐̔̈́̋̈́̈́͘)` will print the same string, since my machine's locale is utf-8. So python2 does the same thing as 3 with regard to machine encoding.
The beauty of LANG=C is that it's the only true lingua franca of modern computing. It's a place where all software and programmers can "meet" without privileging any particular locale.
We have 'gettext' and friends for speaking to humans in particular locales. Embedding i18n into core system design just doesn't work.
This doesn't matter. I'm not sure why you think this matters or what problems will be caused, but a server using a unicode locale (C.utf8 or en.utf8) doesn't localize things for those clients, it just is able to not crash when printing their usernames to log files.
The usernames could be from a variety of locales. If showing them in that form is seen as valuable, they'll each have to be decoded in their appropriate locale. Using LANG=C doesn't prevent this, it encourages it.
Beyond that, as you point out, Unicode provides lots of new opportunities for crashes. Indeed, one of my favorite ways to crash software (software almost invariably running under a "proper" locale) is to feed it a string of (non-ASCII) Unicode. Boom.
No matter the approach, you must code for correctness and deal with all input. For Unicode, you must always allow for decoding failure.
You realize that locales and encodings are different right? En.utf8, c.utf8, and fr.utf8 are all different locales, but are all utf-8 encoded. They'll all work correctly when printed on a machine with any other utf8 locale. The differences arise in things like sort order and regex, where c.utf-8 might be best for a server if you want C or ASCII like functionality.
> Using LANG=C doesn't prevent this, it encourages it.
Well no, because you don't know what encoding each person is using. Either you guess which is error prone, or you have to control the other endpoint so that they include the encoding. But if you control the client, just use utf-8.
Pretty much no software does what you suggest. Go and rust, for example, go further and entirely ignore the system locale and just always use utf-8 for everything. People don't complain.
But my God, could this shit possibly be any more byzantine?
(And why doesn't LANG=C just cause c.utf8 to be used?)
Thus Python3 failed (and frequently, continues to fail) to be a compelling upgrade to anyone but unicode purity fetishists.
Huh? No new project of any note is using 2. Everyone has either upgraded to 3 or never even learned 2 to begin with.
This is something people are getting paid to do; maintain their codebase and keep it up-to-date.
https://youtu.be/0kXaLh8Fz3k?t=322
Personally it’s long been dead to me.
except for COBOL, which has the Schrodingers' property of having been (called) dead for 40+ years, but also somehow powering the world and its' infrastructure.
Does "subsidized zombification" count for a programming language being otherwise dead?
Side Note: 20 years ago a SciFi book introduced me to the idea of "Software Archaeology". These days, such a term is slowly gaining traction as a job description. I've had to professionally dabble into this myself from time to time.
Pay us money.
Sometimes one's only purpose in life is to serve as a warning to others...
This was the best way to do it. Slowly and painlessly. Any project that matters is now on 3.
For a bad transition, look at Perl 6, a debacle so big it was renamed Raku and became a different programming language.
Fractured community Lost trust Endless bikeshedding
All for very little objective gain.
Was it really though? Speaking as somebody who considered learning Python several times over the course of a decade I was seriously put off by the protracted uncertainty around 2 vs 3.
There was a long period - years long - where everything that "mattered" seemed to be supported by and available for Python 2 and there was a ton of FUD, along with genuine issues, about incompatibilities with Python 3. When I asked which version I should learn I felt like I couldn't get a straight answer.
I never had a strong need to learn Python: I just thought it might be a fun and useful thing to do, because people seemed to like the language. But I wasn't interested in investing time in something that might wind up unsupported in a few years, and because I didn't have any serious need for it, it wasn't worth digging through the morass of misinformation to get to the truth.
As an outsider it was extremely unclear to me which version of Python would be actively supported for the long term. 20:20 hindsight says 3 was the future but - and maybe this is just bad mar-comms - back then it seemed like there was a reasonable chance it was either going to be a dead end or exist perpetually in this weird no-mans-land of "not quite ready for prime time".
Had I learned it there's a good chance I probably would have used it for something more serious by now. But I didn't, and so I have to disagree: it was done extremely poorly.
https://bugs.chromium.org/p/chromium/issues/detail?id=942720
I'll be dead in my grave before I recognize anything past 5.8.1.
Just like how they still haven't made The Matrix 3.
Sh. Quiet, you. :)
But it was still full of unnecessary breaking changes.
- The `print()` function is nice, but they could have left in the `print` statement for a transitional (deprecation) period. Or left the `print` statement in, and advise against its use.
- A lot of the incompatibilities are just stdlib modules being moved around unnecessarily. They could have made both import paths work for a transitional (deprecation) period. Or let the old paths continue to work forever, and just document usage of the new paths.
- All the new features in Python 3 (async, nice helper functions, etc.) are compatible with Python 2. They could have added them to Python 2.
The only true breaking change was unicode literal strings. But again, that could be handled with a slow transitional (deprecation) period. The Python 2 stdlib could have been made compatible with both types of strings (as nearly all third-party libraries have). And users could have been told to `from __future__ import unicode_literals` for a transitional (deprecation) period, to ensure their code is compatible before it becomes the default.
Basically Python 3 could have been a single hard breaking change (unicode literal strings), with a smooth transition. Instead they decided to make Python 2 and 3 diverge from each other, making it harder to do the transition.
Or do what javascript did: stay compatible with the stupid old way, but build a brand new language on top of it.
Where do you think the idea for `"use strict"` in JavaScript came from?
They did, it's from __future__ import print_function. python2.7 was, essentially, the transitional deprecation period you mention, and it lasted a decade.
> A lot of the incompatibilities are just stdlib modules being moved around unnecessarily.
six.moves
> - All the new features in Python 3 (async, nice helper functions, etc.) are compatible with Python 2. They could have added them to Python 2.
This assumes a level of similarity in the py2 and py3 codebases that isn't true in practice. There are different bytecodes and 3.0 only optimizations. Backporting some of these is possible, but not a reasonable burden.
>The Python 2 stdlib could have been made compatible with both types of strings (as nearly all third-party libraries have).
I don't know what you're working with, but most third party libs aren't compatible with both types of strings. They're compatible with str or bytes, but not both except in rare and usually wrong cases.
Importing unicode literals only sometimes solves the issues, and often times introduces different problems.
The print statement dates to antiquity (cf. BASIC) and could certainly coexist with the print() function. It was a nice and friendly piece of syntax whose removal was entirely unnecessary.
Now that Python is free of GVR, perhaps we can restore the print statement to its rightful place in the language! ;D
[1] http://python-notes.curiousefficiency.org/en/latest/python3/...
At first glance, you're right. But if you take a closer look, from a purely pragmatic perspective, there are now at least two coexisting ecosystems in two different languages, peacefully sailing along.
Python 2/3 is in this kind of weird twilight zones that the two versions are far away enough that you can't have a smooth transition like in e.g. C++, Java, Rust, Go, etc., but still close enough that there is not a clear cut like in Perl5/Raku. So for a few years, one had to juggle with some of the libs that were 2-and-3 compatible, some that were 2-only, and the others that were 3-only.
C++ et al. let your code evolve Theseus ship-like; Perl makes you build a new ship; and Python tells you that your ship should be OK if you repaint that thing, change a bit of that one, oh, and by the way, you'll have to check very carefully your bunkers, because the boilers will explode if every coal nut is not Unicode-compatible.
Eventually settled for none. I didn't know that at the time, but later it proved to be a career defining moment.
Definitely changed the course of my programming career.
Nothing really wrong with that, but it should have been called "Cobra" or something. And the weird jihad for killing off Python2 should never have happened. If everyone moved to Cobra on their own, great. But there should have been no beatings.
The act of killing off V2 gives downstream developers the right to stop supporting it; regain some focus.
Seems like a strange way to give developers more "rights".
This way there's no expectation, I get to wash my hands of it all. And without an awkward "I'm moving to Viper now chaps". It's a system update paradigm that people understand.
But when you have a few dozen customers on a single product, supporting edge-cases that require core forks becomes incredibly hard. Especially when you need modern Python features.
We tried it. It doubled TTL for simple patches, and meant the Py2 version fell behind in terms of gross features. It was expensive for us, worse for the customer, so we dropped it and moved to a unified core. We had one customer threaten to leave but they didn't. Somebody in their IT department rubbed two brain cells together and agreed with our assessment.
A customer might leave over this sort of behaviour, but again this worked out to be more cost effective, so we would probably do the same when Python 3 is EOL. Wheel keeps turning.
python3: Oh, sorry, you used a feature that was added in 3.x and this system has 3.(x-1) so now you get SyntaxErrors, or worse, random runtime exceptions.
If you can target a container, buildpack or a specific platform python3 is fine, but it's been terrible for developers and users since day one. At least, it's been terrible for me, which is why I still have a pile of stuff to port to python3.
It's fine for something like go or rust to add new features in a dot release, where you just need to upgrade your development hosts. Besides, if it compiles it will work, no surprises later.
But python3 adds new features in 3.5, 3.6, 3.7 and then immediately breaks all new code on older systems.
Used f-strings? Now your code is broken on 3.5.
A new feature used the walrus operator? Now your code is broken on any system that doesn't have 3.8 yet.
And 'dead' python2 keeps working.
> python3: Oh, sorry, you used a feature that was added in 3.x and this system has 3.(x-1) so now you get SyntaxErrors, or worse, random runtime exceptions.
Maybe you were used to Python 2.7 only as "Python 2", but when it was in active development, major 2.x releases had the exact same thing. I had some serious troubles when the latest version of RHEL was on 2.4 while the rest of the world had 2.6 with very large changes. There were all kinds gross hacks just to make things work on an older, common version.
Parent seemed to be talking about the reverse: going backwards, and implying that 2 didn't have major new features, even though it very much did.
Not 100%. For example, using `async` as a variable name works in 3.0 but not in 3.8, where it is a keyword.
https://github.com/search?q=remove+%22walrus+operator%22&typ...
But I mean that since python2.7 came out 10 years ago, python2 has been a stable platform for building things.
Personally, as a developer who has been working on software for a few decades, I've gotten increasingly irritated with the growing churn of platforms today and the astonishing waste of time for everyone who has to deal with it. It's hard to hit a moving target or build on a shaky foundation, but that's what the state of software seems to be today. Instead of platforms approaching stability and spending time on the actual problems at hand, countless developer hours are wasting solving problems created by others "pulling the rug out from under them".
I guess the younger generation of developers just hasn't felt enough of that pain yet, or they're overeager to try new things without thinking of the consequences. I've always taken the conservative approach and as a result some of the software I've written has needed little if any new attention in decades. Some utilities I wrote 25 years ago (not in Python, obviously), I still use regularly. "It's not the tool, it's how you use it."
But you're missing the same point that the parent commenter is missing - stability only came because Python 2 has been sitting at 2.7 for so long.
And you're also missing the point that you can have the same stability by sticking to 3.6 or 3.7 or 3.8 or whatever your fancy is. If you stick with 3.7, I assure you that 3.7 will remain exactly the same and no one is going to pull your rug out from under you. Just don't upgrade.
But don't ask for new features either.
You can always stop now if you want. Download the versions of everything you need and never change. But you'll miss out on the cool new hotness that you're wanting everyone else to miss out on if they stop changing too.
Why doesn't any recent programming languages implement a proper condition system for example? It's not like working implementations hasn't been around for decades.
This industry has a severe case of inability to learn from history so I strongly doubt we'll see things settle down in the near future.
The response was they don’t have enough manpower. The though ignoring deprecated stuff a few releases doesn’t sound particularly hard. I suspect Guido just likes it that way.
Btw, almost no one supports forward compatibility.
The difference is the scope of the breakage. Python 3.0 broke every project. Python 4.0 certainly wouldn't, they are very timid now. In comparison, these breaks are tiny in scope.
It really helps if you think of the versioning as 5.0.x, 6.0.x of Python3, then semver can be applied and you set your shebangs accordingly.
If you use python3 it might randomly fail, if you use python3.8 will fail with 'No such file or directory'
But then if you're trying to write portable Python 3 code without any need for the end user to be pyenv-ing stuff, you probably don't want to be writing 3.8 - off the top of my head, Ansible, for example, targets Python 3.5 for this reason.
I'm not defending this btw, modern Python development is painful, and I taught myself to code in Python, so it hurts to see my first love so.
I guess it would be nice if Python came up with something like Java's source/target which errors if you're using incompatible features.
[0] https://github.com/naftaliharris/tauthon
I am surprised that even 1,000+ languages (at least 50+ mainstream) haven’t satisfied all the wishes and itches. May be that is humanities curse! Creative people constantly want to create a new language and redesign everything while bigger and better problems remain unsolved.
Python 2 vs 3 just seems like yet another thing that breaks up the creative talent pool to waste time solving the same problem in two ways.
LLVM is the first thing I have seen that removes at least some of this duplication. But I hear even Rust is looking at alternate backend! Go doesn’t even use LLVM, all for good reasons I am sure.
What I might agree with is that interoperability is something that should be considered more going forward. I'm unsure about some of them, but Rust focuses a lot on interoperability via FFI, Go's FFI story is bad, as far as I know, Nim's is decent, and I don't knwo about Dart or Swift.
The top languages are all virtually identical. There's so little difference between, say, Java and Python, despite there being so much difference. So maybe there are 50 "serious" languages, but they all fall into a few buckets. There's less meaningful diversity than it seems, I think.
A new programming language is like a new material. You can build chairs and tables in wood. But when a new metal is introduced, is it worth to "duplicate" the work and build chairs in the new material? Maybe, who knows. You may end up with a chair that has surprising new properties, impossible to have in wood. Or maybe it is worse in any measurable way, but some people may still prefer it for some reason. Would you complain to the discoverer of a new material that they should not build chairs in that material, because chairs are already solved (by using wood), and they are just losing time by reinventing the wheel?
Technology advances by the continued reinvention of the wheel. Rewriting old algorithms in new languages is a beautiful part of that.
Most people who actually used Python 2 have zero issue using Python 3. And most people coming into the Python ecosystem now only ever experience Python 3.
The people whining about Python 2 have legacy codebases. And, they have a right to whine, but Python 2 at least will continue to exist. Look at Visual Basic 6 codebases by contrast--more and more of those break with every Windows release.
This is also way different that say the ObjC to Swift transition. Apple simply said "Move, or don't. And if you don't we won't ship your app." And the community moved.
> Regardless of Python 2 vs 3, what is sad is that every new language, be it Go, Rust, Swift, Dart, Nim whatever is dividing whatever set of ‘good, smart, and creative’ engineers we have into smaller group each implementing their own sorting algorithm in their own language.
Sorta, but the whole point of a language is to have a strength that outweighs the negatives of creating it.
If I go through the Tiobe index and look at relatively new languages (there aren't that many in the top--Python, Ruby, and Javascript hardly count as new):
Swift is ObjC moved forward. That one was never going away.
Go is for concise networky client/server thingys. Okay. That's better than most other languages and has some large codebase improvements.
Rust is the only non-GC language in the pile and it aims to be a better C/replace C++--an arena that has been absolutely stagnant for 30+ years.
<dons asbestos suit>
Dart ... okay, you got me. I have no idea "Why Dart?". Every time I interact with it it seems to look like a crappier Clojure with Google foisting it on the world. When your function closings look like this:
You have Lisp-envy. I often wonder if this is just some team inside Google going: "Android Studio is absolutely terrible, anything is better, but we can't budge the glacier. We need to route around the brain damage."D was meant to be a better C--but it took far too long to get a useful non-GC subset so never found its niche.
Scala--Meant to bring Haskelly goodness to the Java ecosystem. In my opinion, overreached, never really achieved its goals and now is competing against better languages. It took FOREVER until the whole Actor system worked decently in Scala, for example. To be fair, it also appeared in like 2000(?) back when the Java language ecosystem was basically crickets chirping. The JVM has improved a lot since then and made language development a lot better.
Kotlin--presumably in the right place at the right time. A modern Java before modern Java. And appeared at the point where Google needs to make sure to have an escape hatch against Oracle if required.
Groovy--Possibly the worst language to have any traction. However, most people's interactions with Groovy come about when they have to fix something broken in the absolutely horrible Android Studio build system. Friends I trust say that Groovy isn't really that bad (but not that compelling) but that, yeah, the Android Studio Build system is a horrible exemplar.
It turns out that Pypy will have Python 2 support. I don't know the details but it sounds like you'll be able to run py2 code using pypy (not pypy3) for N more years.
1. https://w3techs.com/technologies/details/pl-php