Overview of Talk Python to Me #564: EVE Online Departs for Python 3
In this episode, Michael Kennedy talks with Christian Sigurbergsson, Jamie Bannister, and Thomas Dalling about one of the most ambitious Python migrations imaginable: moving EVE Online from a heavily customized Python 2 / Stackless Python runtime to Python 3.12 and beyond. They discuss why EVE’s architecture made this migration unusually complex, how the team handled compatibility and serialization issues across a live single-shard MMO, and what lessons they learned while first proving the transition in EVE Frontier.
What EVE Online Is
- A long-running MMORPG launched in 2003
- Set in a persistent sci-fi universe with:
- mining, trading, piracy, industry, and combat
- a full-loss system where destroyed ships are gone permanently
- a single shared universe, or single shard, where all players can potentially interact
- Famous for its player-driven economy and emergent social structures:
- corporations, banks, logistics groups, democratic/communist-style orgs, and command hierarchies
- large-scale fleet warfare coordinated through in-game and external tools like Discord
Why This Python Migration Is So Hard
- EVE has roughly 2.4 million lines of code
- The game depended on a custom Stackless Python runtime:
- built for asynchronous, coroutine-like gameplay before modern
asyncio - tightly integrated with custom threading, socket, and scheduling behavior
- built for asynchronous, coroutine-like gameplay before modern
- The game must remain online continuously
- no long downtime
- no “big bang” migration is acceptable
- A lot of the code and tooling predate modern Python conventions, package management, and testing practices
Stackless Python: What It Meant for EVE
Why it existed
- Enabled game logic to be written in a simple, sequential style while actually running asynchronously
- Helped non-specialist developers and designers contribute gameplay code
- Supported EVE’s need for concurrency and scale long before mainstream async patterns were common
Why it became a liability
- It was a custom fork of CPython, with additional internal changes
- Third-party Python packages were hard to use
- Native extensions and environment setup were fragile
- Upgrading Python versions became increasingly difficult because of the interpreter changes and bespoke runtime behavior
The Migration Strategy
The team described a staged approach rather than a direct leap:
1. Normalize legacy code to Python 2.7-compatible style
- Use automated tools like futurize
- Replace older idioms such as:
dict.has_key()→in- other Python 2-only syntax and patterns
- This brought the codebase from roughly 94% to 99.8% Python 3-syntax-compatible
2. Separate into Python 2.7 and Python 3 branches
- The Python 3 branch started failing tests immediately, as expected
- A compatibility branch was used to introduce shims and adapters
- This allowed the team to keep forward progress while maintaining compatibility for active development
3. Fix runtime and data compatibility
- The migration is not just about code:
- serialized Python objects
- network payloads
- data at rest
- A major concern is old pickled objects stored in the database, including about 100 GB of agent memory data
4. Prepare for mixed-mode deployment
- The goal is to incrementally replace parts of the system rather than do a risky full cutover
- This includes the possibility of:
- some nodes on Python 2, some on Python 3 during transition
- eventually mixed platform deployment improvements as a side effect
Technical Challenges Discussed
Division semantics
- Python 2 and Python 3 handle division differently
- EVE identified about 6,500 lines involving division
- This matters a lot in combat math, damage calculations, and game balance
Pickle and object serialization
- Old Python 2 pickles may not deserialize cleanly in Python 3
- Some game systems, like NPC agent memory, store long-lived serialized Python objects
- The team is likely moving toward protobuf or flatbuffers for more stable serialization
Windows-centric, custom deployment
- EVE historically shipped with its own embedded interpreter and custom environment
- Developers often had to fight:
- environment path issues
- bundled Python conflicts
- native extension compatibility
- The lack of a clean package manager made dependency management painful
Why EVE Frontier Mattered First
- EVE Frontier shares much of the same underlying technology stack
- It served as a lower-risk proving ground for the Python 3 transition
- Frontier let the team learn hard lessons before applying them to EVE Online, where uptime requirements are stricter
- Early Frontier deployment issues helped expose hidden assumptions and stability problems
Future Direction
- The team is moving to Python 3.12 now
- They already have plans to go further, including a later jump to Python 3.15
- They’re also evaluating:
- free-threaded Python
- improved package management and developer workflows
- better typing and static analysis support
- The team expects performance and maintainability improvements from modern Python, even without adopting every new concurrency feature
Key Takeaways
- Migrating a massive live game from Python 2 to Python 3 is less about syntax and more about:
- runtime behavior
- serialization compatibility
- deployment tooling
- test coverage
- operational risk
- Modern Python brings tangible benefits:
- better typing support
- improved performance
- easier dependency management
- more maintainable code
- Incremental, well-controlled migration is essential for systems that can’t afford downtime
Advice for Teams Facing Similar Migrations
- Keep the migration isolated
- dedicate resources to it so feature work doesn’t derail progress
- Do it in small, frequent steps
- avoid giant, infrequent merges
- Invest in tooling
- linters, compatibility checks, and automated validation matter a lot
- Be conservative about dependencies
- especially when your environment is customized or long-lived
- Use a lower-risk system first if possible
- prove the process in a smaller or less critical codebase before migrating the flagship product
Notable Insight
“If you start, you have to finish it.”
That sentiment captured the tone of the episode: this is not a casual upgrade, but a long, disciplined engineering project where planning, tooling, and risk management matter as much as the code itself.
