Saying that it was finally time for the community to bid a “fond but firm farewell to Python 2”, core developer Benjamin Peterson marked the release of Python 2.7.18 on April 20th; officially ending support for the 2.x branch of the popular programming language. It was hardly a snap decision. Python 3.0 was released all the way back in December 2008, and it was never a secret that the newer branch was not only incompatible with the earlier version, but that it would eventually superseded it to become the standard.

But migrating the incredible amount of Python code in the wild over to the latest and greatest was easier said than done. Millions upon millions of lines of code used in everything from Linux distributions to virtually every major web service needed to be reviewed and migrated over to Python 3. In many cases the changes were relatively minor, but when code is being used in mission critical applications, even the smallest of changes are often avoided unless it’s absolutely necessary. The voluntary migration took far longer than expected, and the end-of-life (EOL) for Python 2 was pushed back by years to accommodate developers who hadn’t made the necessary changes yet.

Given the somewhat fluid nature of the Python 2 EOL date, it seems fitting that this last final release would come several months after the “official” January 2020 deadline. The intention was for it to coincide with PyCon 2020, but just like so many of the events planned for the first half of the year, the in-person conference had to be canceled in favor of a virtual one due to the COVID-19 epidemic. That might have stymied the celebration somewhat, but the release of Python 2.7.18 will still be looked on as a special moment for everyone involved.

Too Big to Fail

If everything had gone according to plan, this milestone would have been celebrated sometime in 2015 as that was the sunset date originally announced back in 2008. But as the EOL date got closer, it became clear that the community simply wasn’t ready to make the switch. The problem was complicated by the nature of Python development, which generally involves pulling in a number of upstream libraries. Even if individual developers were ready and able to move their code over to the newest release of Python, the libraries their project relied on might not be so agile. Until large and popular libraries made the switch, end-users were stuck in limbo.

For the hobby Python user, getting your code ready for Python 3 was often as simple as making sure your print() functions had the proper syntax. But migrating a huge library was another story.

There were many changes to the more esoteric functions of the language that needed to be taken into account, which meant updating would eat up a large chunk of development time; not something many open source libraries have an abundance of to begin with. Without a clear advantage to moving their libraries over to Python 3, many developers simply decided not to.

In a perfect world, it wouldn’t matter if people wanted to stick to the older version they were more comfortable with. But we don’t live in that world, and with so many websites and online services relying on Python 2, the fact that developers weren’t updating became a liability. Those in charge of large Python projects were often left with an unenviable decision: either live with the known bugs and security issues, or make the leap to Python 3 which will break backwards compatibility and require refactoring large swaths of code.

Seeing the magnitude of the situation, the Python developers introduced PEP 466 — Network Security Enhancements for Python 2.7.x in 2014. This update specifically addressed the aging implementation of SSL in the older Python series which was seen as a serious security risk for projects that were unable or unwilling to upgrade to the 3.x branch. It was a deviation from how feature updates were normally handled in the Python development process, but it was deemed necessary given the circumstances.

As Peterson noted in the Python 2.7.18 announcement: “Traditionally, these features would never have been added to a branch in maintenance mode, but exceptions were made to keep Python 2 users secure.”

The Future of Python 2

Despite having more than a decade to prepare, it would be naive to think that every project has migrated over to Python 3. The largest and best known libraries have switched over at this point, or are at least are in the process of doing so, but there’s no question that there’s plenty of Python 2 code still running out there. We’ve recently been reminded of how many critical systems are still running COBOL, an archaic language now over 60 years old. It seems inevitable that pockets of Python 2 code will remain in operation for years or even decades to come, simply because nobody wants to go in and rewrite something that’s already working.

Will your banking information or other critical data pass through some Python 2 code today? It’s certainly possible, perhaps even likely. It probably won’t even be Python 2.7.18, either. That’s not necessarily a problem right now, but any bugs and security vulnerabilities discovered from this day forward won’t be fixed. They might not even get reported through official channels. Anyone running an unsupported version of Python shouldn’t expect much help coming their way when the next major vulnerability is discovered.

So in the future will we be reading about companies scrambling to find Python 2 developers that know how to fix an entrenched piece of software that hasn’t been updated in decades? Luckily, the two versions of Python are similar enough that updating the code is generally more a matter of time than difficulty. We should have developers who are capable of doing the job for the foreseeable future, but it might not come cheap.