It was methodical and deliberate, but slow.
But I think it really happened because developers wanted to move to 3. There was enough momentum and upside for moving to 3 that the Python core developers could keep the migration on track without having to drag people along from 2 -> 3 before they were ready. Making sure that the transition was optional for a long time helped tremendously.
I was quite happy working in Python 2 for a long time and only transitioned over to 3 for new projects or code that I thought would have a long lifetime. This was very much a reason why I moved to 3 instead of to another language.
At the same time, I'm not sure what language I would have switched to for the things I was using Python for... Perl was out as it had it's own disastrous migration. Ruby was an option, but never really hit the general-purpose scripting language mark for me.
Uh.. You've started in the middle. Python 3.0, 3.1, and 3.2 were insufficiently compatible to support a migration. If not for the effort to reduce 2 to 3 incompatibility by shipping 2.7 and 3.3, 3 could really have failed. I'd say the initial plan was not so good but then the _replan_ after the first setbacks was good.
Actual language standards that multiple stakeholders agree on are a much better approach.
Platforms should absorb pain, not multiply it across all developers that use the platform. (I wish Apple would learn this lesson.)