What most people don’t seem to realize is that there aren’t only language changes to contend with, but framework changes as well. This line is further blurred in language-framework pairs like C# and .NET, where (as a web dev) you’re pretty much always going to be using .NET if you’re using C#, whether you realize it or not. In these cases, framework revisions are what getcha, not language changes. Microsoft does a good job of maintaining backwards compatibility as C# the language changes, but framework upgrades (eg .NET Core 3.1 to .NET 5) will absolutely cause headache via runtime exceptions, etc.
So yeah Python ain’t that bad. I can’t speak to frameworks like Django, though.
Django was actually fine. They had the same codebase running on Python 2 and three, so you could update whenever. Since Django includes so many batteries, I didn’t have any trouble porting that over.
However, early versions of Python 3 were slower than Python 2, and also some breaking changes were getting rolled back (e.g. PEP-414, which was targeting Python 3.3), which contributed to a lot of library authors dragging their feet in upgrading their support.
So, yes, it was libraries causing the most headaches, but there was a sense at the time of wondering when the upgrade would become “real”. Depreciating py2 took 11 years after the release of 3.0.
So yeah Python ain’t that bad. I can’t speak to frameworks like Django, though.