For all the complaints, Python 3 was incredibly conservative about making changes that would completely break existing code. String handling was basically the big shift, and if you were writing good code to begin with wasn't super hard for most problem domains to adjust to. Clearing up some cruft in the way the standard library was organized wasn't hard to deal with either. And there wasn't a lot of new syntax in 3.0/3.1 and quite a bit of it was backported into 2.6/2.7 to make the transition easier.
And then there was a bit of a moratorium on language changes in 3.x to give people time to catch up from their 2.x codebases.
The result of which is a lot of people who didn't think Python 3 was a big enough deal to be worth putting in the effort to migrate, when the 3.x series started releasing. And now many of them are finally noticing all the cool stuff that's in 3.x now (3.6 is about to release), and noticing that their favorite tools and libraries have switched from "we support 2 and 3" to "we're dropping support for 2", and realizing they didn't take advantage of all the time they had to port stuff, and are angry and feeling left out and trying to find complaints to level at Python 3 in the hope that enough people will agree and just magically end it, port all the new features back to Python 2, and let them keep going as-is.
I could also be because there was another choice (which is what you also said). Ruby 1.8 -> 1.9 was annoying, but you weren't going to keep using 1.8 given e.g. the speed improvements of 1.9. (Also, who adds breaking changes in minor version numbers?)
There's a great talk about changing the culture around Python3 at Facebook[0], I highly recommend it. Technically, it isn't so hard. Culturally, it can be pretty hard. Calling Python2 "Legacy Python" helped at my $work. My boss agreed that continuing 2.x development wasn't a good investment for the future, given the minor technical challanges involved with moving over a few years.
When Arch switched from /usr/bin/python being python 2 to being python 3, buckets of python scripts failed. When downloading third-party python programs, the only way I know to know which version of python to use is to try one and when try the other when it complains about syntax errors.
With a perl-style "use" declaration, the runtime can immediately tell you when you're using the wrong version, or even, in principle, switch to the correct runtime if it's installed.
Hashbangs should refer to a version: e.g. "#!/usr/bin/env python2". Github shows approx. 3M results for "/usr/bin/env python", but less than 200k combined for version-specific hashbangs.
For loose scripts this is the way, "env python" is simply wrong. Always use "..env python2" or "..env python3"; it works everywhere, and where the correct version is not installed it gives a relatively helpful error message (something like "No such file or directory: "python2" ").
Of course, there will always be those who find problems with any change and they're normally the most vocal.
Personally, I've struggled with various unicode issues in my code over the last few years and python3 might have saved me from all that. Even so, for a long time python3 didn't seem to offer enough of an advantage to make the switch although I have ported some of my code across which was relatively easy.
The hardest thing for me is that python3 has banned implicit relative imports within packages. Unfortunately I've tended to mix modules and scripts freely in my projects (scientific simulations) and so I'll need to restructure to port some of my projects.
Here's a non-example: Ruby. It was quite possible and not even that difficult to write code that ran on both Ruby 1.8 and Ruby 1.9 that had correct behavior for both systems, despite all of the pain people noted about the transition with Unicode just trying to use vanilla 1.8 code on 1.9... but the transition from Python 2.7 to Python 3.0 required an all-or-nothing approach for the numerous changes which could not be "from __future__ import"ed in 2.7: Python 3.0 almost seemed to go out of its way to screw with developers, renaming "str" to "bytes" and "unicode" to "str" without providing any aliases which could be used across the different runtimes and simultaneously removing the u"" prefix syntax while remapping "" (so there was no cross-version way to even say "this represents text). Even later versions of Python still didn't try to help with exceptions: the syntax simply changed and the only way to write code that worked on both was to catch exceptions without a name and then dig into sys.exc_info() to pull the value as part of the except block.
Meanwhile, the Python developers handled the bootstrap horribly: they have been giving the finger to people for using Python 2 ever since they started working on Python 3, putting 2.7 in what was essentially an "emergency maintenance only" mode, causing the runtime to stagnate for five years while they marched from 3.0 (which was nearly unusable) to 3.5 (which was where Python 3 started to look reasonable) and there was very little library uptake; so it isn't like higher-level code could transition even if it wanted to: application developers were stuck waiting on libraries and library developers were stuck waiting on the language itself to become more reasonable, and in that five year gap many people just started jumping ship to entirely different languages--such as Go, Rust, Clojure, and Elixir--as it isn't like they really had a choice (as again: they were blocked on people who were blocked on other people).