Python 2 Migration
for businesses in Australia, New Zealand, the UK and the US.
Python 2.7 reached end of life on 1 January 2020. Every current library targets Python 3, so a Python 2 codebase is frozen against a set of dependencies that stopped receiving fixes years ago.
- Independent No licence commission, no reseller agenda
- 18+ yrs Building business software
- Fixed Price scopes, no surprises
- AU NZ UK US Perth-based, working remotely
Frozen since 2020, and quietly accumulating risk
Python 2 code tends to be scripts and services that do something important and unglamorous: processing files, moving data between systems, generating reports, running scheduled jobs. Nobody looks at them because they work.
The exposure is in the dependencies. Every package pinned to a Python 2 version stopped receiving security fixes, and the strings-and-bytes distinction that makes the migration awkward is exactly what makes automated conversion unreliable.
Your Python 2 project, end to end
Three stages. Scoped and fixed-price before anything starts, delivered by the founder, and your existing system stays running until cutover.
-
Week 0
Read the system as it is
We go through the existing application and record what it actually does, including the parts nobody documented. You get a written inventory and a fixed price before any build starts.
-
Weeks 1-N
Rebuild and run in parallel
The replacement runs beside the original until the numbers reconcile. The old system stays untouched and switched on the whole time.
-
Cutover
Go live and hand over
Cutover on a date you choose, then thirty days of support. Source code, documentation and credentials are handed to you, in your name.
What the work actually is
Convert deliberately, and verify the string handling
Automated conversion gets part of the way and hides the part that matters. The strings-and-bytes change is where behaviour shifts silently, so the work is deliberate conversion plus tests that prove the output has not changed.
What you have now
- Python 2.7 scripts and services
- Pinned packages with no Python 3 release
- Scheduled jobs nobody documented
- A server kept on an old OS for this
Convert deliberately, and verify the string handling
Automated conversion gets part of the way and hides the part that matters. The strings-and-bytes change is where behaviour shifts silently, so the work is deliberate conversion plus tests that prove the output has not changed.
See how a project runsWhat you end up with
- Running on current Python with maintained dependencies
- Tests around the behaviour, often for the first time
- A server that can be patched again
The 5 pieces of Python 2 work we are asked for
Most engagements are some combination of these, and most start with the first.
Inventory the dependencies
Which packages have a Python 3 release, which are abandoned, and which need replacing. This usually determines the effort more than the code does.
Convert the code
Automated tooling as a starting point, then a deliberate pass over the string and bytes handling where silent behaviour changes hide.
Write the tests first
Capture what the current code produces before changing it. Without that you cannot prove the migration preserved behaviour.
Replace abandoned packages
Anything with no Python 3 release gets a maintained equivalent or a small purpose-built replacement.
Modernise the deployment
These scripts usually live on a server kept old solely for them. Once converted, that constraint disappears.
Where you are now
It works, and nobody will touch it
- Python 2.7 past end of life since 1 January 2020
- Pinned packages receiving no security fixes
- A server held on an old OS purely for this code
- Nobody certain what the scripts actually do
After
Supported, documented and yours
- Current Python with maintained, patched dependencies
- Tests that prove behaviour was preserved
- Deployment on a supported operating system
- Documentation of what each job actually does
Scoped and quoted before you commit. You own the code, the documentation and the credentials at the end of it.
Get a fixed-price scopePython 2 questions
Can 2to3 do this for us?
It gets part of the way and it will not tell you about the part that matters. The strings and bytes distinction changes behaviour silently, so automated conversion needs a deliberate review pass and tests behind it.
Our code works fine. Why change it?
The code is not the exposure, the dependencies are. Packages pinned to Python 2 stopped receiving security fixes in 2020, and the server is usually being held on an old operating system to keep them running.
We have no tests. Is that a problem?
It is the first thing to fix. We capture what the current code produces and turn that into tests, so the migration can be proven rather than hoped. It is also useful long after this project ends.
What if a library we depend on has no Python 3 version?
Either a maintained equivalent exists, or the small part you actually use gets rebuilt. In practice most codebases use a fraction of the libraries they import.
Is this urgent?
It depends on exposure. An internal script on an isolated server is a slow burn. Anything processing external input or reachable from the internet should be dealt with now.
Sending your details…
You can stay on this page while we send it.
Tell us what you are running
What the system does, roughly how old it is, and what is forcing the question. We will come back with a straight answer and a fixed-price scope, even if the answer is to leave it alone.
Prefer a quick chat? Call 0425 531 127. We answer the phone in Perth.