now, i'm not brave enough to say that i could have done python3 better. migrations, adoptions are often driven by social factors, rather than technical ones, and there's only so much you can get right the first time—and there's just a lot of things you can get wrong, too
don't get me wrong, python3 was an awkward, painful process, but unlike Perl6 (Raku at time of writing), the community moved forwards, albeit with a lot of dragging. the question isn't "could we have done better" but "if we did it again, what might we do differently?"
i can't claim to speak for every person who found the python3 process bumpy, but there are some common grievances:
maybe don't break the abi at the same time as breaking the language
this, by far and large, was the biggest mistake of python3. it wasn't just a new language, with new libraries, but one with new extensions, cleaning up ancient c apis long overdue for change.
python3 created a chicken and egg problem
- end users didn't want to move to python3 if the libraries they were using didn't work yet
- extension authors didn't want to maintain two versions of their software, so held back from updating to the new api, until users started adopting the language
then they made it worse: you couldn't just port code over if it used bytes
yes, some of us are forced to use bytes
python's unicode support needed changes, and desperately so. python3 is free of the dreaded unicode decode error, and many a python2 project would contain chains of encode() and decode() to ward of such evil through any means.
python3 drew a line: strings would be unicode strings by default, input and output handles would take unicode strings by default, you just wouldn't be using bytestrings
and then, python kinda went, "actually, fuck you." it took several minor versions and several heated exchanges but ultimately python gave in: they implemented the features the library authors needed.
2to3 didn't work, six did
let me be clear: no-one wants to maintain two near exact copies of the code.
at the time, 2to3 was the hailed solution to the problem: 2to3 would turn your code into python3, but with the same semantics as before, and you'd only need to run it once. which didn't exactly play out as planned.
it turns out, even when one is mostly autogenerated, no-one wants to maintain two near exact copies of the code. that's why people started using six. it wrapped library imports so you didn't have to write so much conditional code.
migrations are slow. not everyone can shift major versions at once. you had to write code that ran under python2 and python3, and with not that much effort, you could. from future import print_function is a great idea.
so, what's the moral?
- don't break your abi and language at the same time
- people would rather portable code than code generation
- deprecating core functionality
there is a point to be made here in that there's a lot of unpaid work and sitting around posturing about "what i would have done" isn't helpful.
the point is more "i hope python4 doesn't do this again, if we ever get there"
