You could have broken down those changes into small pieces, with deprecation. But then, you would have spent the last 10 years changing your code every 2 years. I don't think that's better.
Look at the JS community. They break things every 6 months. The result ? Oh they are moving fast.
But most projects I met in JS are disposable ones. They will not evolve. They will not be maintained. They will be trashed and rewritten.
So yes, the transition has issues, and it could have done it better. But it's far from as bad as most people say it is. People just like to be have everything without paying any cost, but it doesn't work. They want a modern language, but that never changes. They want something stable but that stays up to date. They want to write code and never touch it again, but then complain they can't use their shinny new toy.
And seriously, I always hear about those too many huge hours spent to port code 2 to 3. That is so much bullshit.
I do that regularly with my clients, and that's far, far away from the reality. Unless you have some very exotic code, it's a few minutes per files. Something you do anyway cause you redactor and clear your code.
The team of numpy, twisted and dropbox did suffer from the port. But come on, most people are not them. And THEY didn't complain. People that don't have the problem usually complain the most. They are just scared of the movie they played in their head. They all think they are a special snowflake.
Without the ability to mark variables as constants, a switch-case can't implement an efficient jump table. And without a jump table, a switch/case statement is merely syntactic sugar for an if/elif/elif chain.
Now everyone uses python 3 and has stopped griping, which wasn't warranted in the first place.