That would have made cross-version codebases impossible, and that's what ultimately allowed migrating. One-shot migrations were not convenient, or successful, or even effectively feasible for complex enough projects.
What allowed the migration was community experiment in cross-version sources, as well as reintroduction of "compatibility" features into Python 3.
And if you wanted to try that yourself anyway, changing all .py to .py3 in a directory is one unix command... It could easily have been part of a 2to3 tool
I was personally and solely responsible for migrating a >250kLOC project from Python 2 to Python 3, doing so without cross-version compatibility would not have been feasible. We literally picked the earliest P3 version we decided to support based on cross-compatibility features.
- the codebase had to be modified to work on both versions at the same time
- you had to maintain two versions in different branches for a while
Is there any data to show which options was most often chosen amongst all pypi packages? I suspect that the second option was more popular for the most important packages of the ecosystem
six was the #2 package on PyPI.[1] It's a library to help with option 1.
You're 100% wrong. The few packages which decided on option 2 early on (e.g. dateutil) ended up having to roll back to option 1 because it was such a pain in the ass, both for the maintainer and for downstream users. The migration only really started happening once 2.7 dropped, projects like Six[0] started appearing, and the community started ignoring 2to3 and building up experience with cross-version projects and idioms (e.g. [1], [2])
[0] whose entire point is to help with option 1
[1] https://eev.ee/blog/2016/07/31/python-faq-how-do-i-port-to-p...
This. This is the only option.
I can tell you in decades of experience with I don't know how many companies and language, this is ALWAYS the option that is done.
In your shell you don't run "java8" or "java11", you just run "java", and then it's the matter of what version of java JDK you have in your PATH. The same with all other language interpreters and compilers, you don't run gcc9 or node14. Why doing something different for python?
Really, the mistake of python3 was to break compatibility with past programs. A lot of changes could have been done more gradually, in the first version require a __future__ import, then gradually remove compatibility with old features, and then remove them completely, making the new way the default and thus no longer require the __future__ import. And I think it will be the way for next python version, so in theory we will never have the same problem again.
Also to me it was an error for distros to continue packaging python2 as python. Other distributions, like ArchLinux, switched everything to python3 as default a lot of time ago, it's only Ubuntu that continued to ship python2 as python, thus making a lot of programmers relying on it. It would make sense that the command without the name refers to the latest version, and not the legacy one.
That's not the case with C# or Java.
But there was a sort of broken promise given by the Python creators: Python3 was almost like Python2, but every library author had to review and repackage their libraries, anyway.
At that point, Python 3 should have been unambiguously incompatible with Python 2 :
The mistake was that you could use "pip" or "python" in bash scripts/shell, and not know if python2 or python3 were going to run.Still today, you can run "python" in a recent version of Ubuntu or Fedora, and it will be Python 3. Only "python3" should be possible. Distro are repeating the same mistake than with Python 2, and we will struggle again with Python 4, if there is any Python 4.
Many headaches wouldn't have happened if "python" was reserved to Python 2.
Pro tip to language and distro maintainers : make the major version part of the language name and executable, from version 1.