Should You Update to the Latest Python Bugfix Version?

Should You Update to the Latest Python Bugfix Version?

by Geir Arne Hjelle advanced best-practices devops

If you’ve been hanging out in the Python community for a while, you may remember discussions about Python 2 vs Python 3, or you may have seen versions like Python 3.10 and Python 3.11 released with some fanfare. You may have noticed that Python versions have three numbers—for example, 3.10.8. In this tutorial, you’ll focus on Python bugfix versions and the importance of that third number.

For any developer, designing a versioning scheme and interpreting the corresponding version numbers is its own little art form. Some of the most popular systems are calendar versioning and semantic versioning. Python’s versioning scheme resembles semantic versioning, but with some crucial differences.

Typically, a version number is given as a tuple of three numbers, often referred to as MAJOR.MINOR.PATCH. The interpretation of the three numbers depends on your versioning scheme:

  • MAJOR is the most important number. In calendar versioning, this is often the year of a release. Semantic versioning schemes introduce new major versions when there are backward-incompatible changes. Python last updated its major version when Python 3 was released in 2008, and there are currently no concrete plans to release a major version 4 of Python.

  • MINOR is the second version number. This number keeps track of regular releases that offer some new functionality while remaining compatible with the previous version. In Python, a MINOR release is usually called a feature release and may remove deprecated features. The Python community releases a new feature version annually, typically in October.

  • PATCH is the third and least significant number. It’s sometimes named MICRO instead. Versions that only differ in their PATCH numbers will typically have the same functionality. In Python, a PATCH release is often called a bugfix release, a maintenance release, or a security fix release. As the names suggest, these versions will only introduce bug or security fixes.

In Python, these numbers follow a fairly strict schedule. Each feature, or MINOR, release of Python goes through the same life cycle:

The life cycle of Python feature releases
Python feature release life cycle

The diagram shows the life cycles of Python 3.11, 3.12, and 3.13. The PATCH numbers track where in its cycle a version currently is. Development starts about seventeen months before the release date:

  • New features are developed during the first twelve months and are released in alpha versions.
  • The version is thoroughly tested and prepared for release in the next five months. Beta and release candidate versions are published during this time.
  • Bugfix releases are published regularly for eighteen months after the feature release.
  • Security fix releases are published as needed until five years after the feature release.

The alpha, beta, and release candidate versions are collectively known as pre-release versions. For each feature release, these are made available during the development and testing phases. You should start testing your code on these early versions, but you shouldn’t run essential services on them.

In this tutorial, you’ll focus on the bugfix and security fix release versions. While new feature releases of Python get some buzz because they introduce new features to the language, the difference between, for example, 3.11.0 and 3.11.1 may be harder to spot. Should you update to the latest bugfix version of Python?

In Short: Yes, Especially in Vulnerable Production Systems

Keeping up to date with the latest maintenance version of the Python feature release that you’re using is a good idea!

In specific contexts and use cases, it’s even more critical. As in all large software systems, there are bugs in Python. Few of these will affect you, but from time to time, a vulnerability is discovered and fixed. If you deal with sensitive data or a system exposed to users who may have evil intentions, then you must keep up with the latest bugfix version to protect yourself and your users.

If you don’t update to the latest maintenance version, then you’re not missing any new features of Python. Those are all added in feature releases. So, the main question you should consider is how exposed and vulnerable your system is. If your system is potentially open to an attack that could have severe consequences, then you need a process to ensure that your environment is as robust as possible.

You should manage your project through an automated continuous integration system that’ll run tests on all your updates. To be alerted about new bugfix releases of Python, you can follow release posts on Python Discourse or subscribe to the Python announce mailing list.

Bugfix releases will only contain bug and security fixes. You most likely won’t experience any difference between two versions of the same feature release. If you’re not hitting any lurking Python bugs and not touching the outside world when running your code, it’s less urgent to always use the latest maintenance version.

That said, even though the risks and consequences of security issues are smaller in your hobby projects, it’s still a good habit to work on a reasonably up-to-date and secure version of Python. Ideally, you should find a workflow that makes it convenient to run different versions of Python and update to new ones.

How Can You Conveniently Keep Up to Date With New Versions?

How you update your production systems to the latest bugfix version depends on your setup. Ideally, you can change the version number in a configuration file and rerun your tests.

In this section, you’ll look at one possible workflow for handling different versions of Python on your local computer. In your workflow, you should control two separate aspects of your programming setup:

  1. The version of your Python interpreter
  2. The versions of your Python packages

In general, several versions of Python can coexist on your system. You can manage your Python versions manually or use a tool like pyenv or conda.

You should use virtual environments to handle the Python packages that you depend on. When you create a virtual environment, you tie it to a specific version of Python. To update the Python interpreter, you, therefore, need a convenient way of re-creating your virtual environment.

To make sure your virtual environment is reproducible, you can use a lock file that lists all your dependencies and their individual versions. It’s possible to create such a lock file manually, but using a tool is usually a better option. Again, you have several options, including pip-tools, Poetry, conda-lock, and Pipenv.

You can choose and combine the tools that work for you. Here’s one example of a workflow using pyenv and pip-tools. You need to install pyenv as a separate application, while you can use pip or pipx to install pip-tools.

When you start a new project, you should create a separate project directory for it. You’ll do all the following commands within that project directory.

First, specify your dependencies inside a plaintext file named requirements.in. For example:

Python Requirements
# requirements.in

rich
typer

You’ll only define your direct dependencies in this file. In general, you don’t need to add any version markers here.

Next, lock your dependencies using pip-tools:

Shell
$ pip-compile requirements.in

Running pip-tools generates requirements.txt, which contains all your dependencies, including indirect ones:

Python Requirements
# requirements.txt
#
# This file is autogenerated by pip-compile with python 3.10
# To update, run:
#
#    pip-compile requirements.in
#
click==8.1.3
    # via typer
commonmark==0.9.1
    # via rich
pygments==2.13.0
    # via rich
rich==12.6.0
    # via -r requirements.in
typer==0.6.1
    # via -r requirements.in

Pip-tools pins each dependency to a specific version. It also adds valuable annotations that show why it included each dependency. You can rerun pip-compile when you add new dependencies in requirements.in. If you want to upgrade your dependencies to new versions, run pip-compile --upgrade.

You’ll add your requirements file when you start a project, and you’ll maintain it continuously, independently of when you update Python versions. You don’t need to update your dependencies when you install a new bugfix version. Instead, you’ll make sure to install the dependencies in a new virtual environment.

To update to the latest maintenance version, you’ll first install a new Python version with pyenv and activate it:

Shell
$ pyenv update
$ pyenv install 3.10.8
$ pyenv local 3.10.8

You can use pyenv install --list to see a list of available Python versions.

Next, create or re-create your virtual environment and activate it:

Windows PowerShell
PS> python -m venv venv --clear
PS> venv\Scripts\activate
Shell
$ python -m venv venv --clear
$ source venv/bin/activate

Use --clear to ensure that your virtual environment is cleaned up, even if you already had it created with an older version of Python.

Finally, install your locked dependencies into the new virtual environment:

Shell
(venv) $ python -m pip install -r requirements.txt

If you always add dependencies through requirement files, then you’ll be confident that you can re-create your environment. While this discipline may seem cumbersome, the investment will pay back many times over and help you update your Python interpreter without much hassle.

If you work with other tools, then the details will be different. However, you should be able to follow the same main steps.

What Can Go Wrong When Updating to Python’s Latest Bugfix Version?

Python maintenance releases only introduce a few types of changes. The focus is on fixing bugs and security issues. There shouldn’t be any new features or changes in how existing functions behave.

Still, you should always run your tests after updating to a new Python version. If you don’t have a lot of tests in your hobby project, then at least run your code to confirm that nothing obvious has changed.

While the risk of running into issues is low, there are a few possible scenarios that you should be aware of.

Python is a complex piece of software, and there are times when fixing one bug introduces another. Some bugfix versions may contain unexpected regressions. For example, Python 3.10.3 introduced a bug that made Python unusable on an older Red Hat Enterprise Linux version.

Python’s core team handled the regression and released Python 3.10.4 earlier than planned.

Sometimes, you may have unconsciously been relying on the behavior of a bug in Python. If that bug is fixed, then you’ll find that your code stops working. In this case, you need to update your code. It may be tempting to leave your code alone and stop updating Python instead. Doing so will work in the short term, but it isn’t a sustainable solution.

While rare, it sometimes happens that a security fix affects your code. For example, Python 3.10.7 disallows conversion between string and integer types for very large integers. Python introduced the fix to prevent a certain kind of attack. However, this also meant that some code valid in earlier versions of Python no longer worked.

Making such significant changes in a bugfix version is controversial and doesn’t happen often. It’s not fun if your project is affected by such a change. Still, your best option is to update your code to continue using the latest bugfix versions.

Are Python Maintenance Releases Compatible With Each Other?

As noted, no new features are added or removed in bugfix releases. Therefore, your code should generally work the same across all maintenance releases of a given Python version.

Additionally, CPython’s application binary interface (ABI) to communicate with C extensions is stable across all bugfix releases. This stability means you can use the same wheel of a third-party library when updating your bugfix version. In other words, you don’t need to update your requirement files.

Should You Also Update to the Latest Feature Version?

Updating to the latest feature version of Python is a very different consideration from updating to the latest maintenance version. Luckily, you can make these decisions independently of each other. Even if you stay on an older feature release, you can ensure that you use the latest bugfix version of that release.

New feature releases introduce new features and deprecate and remove old ones. Therefore, there’s a higher risk that your code will break if you upgrade. You should be diligent in your testing before making the switch.

One issue that may hold you back from upgrading to the newest and shiniest version of Python is that the application binary interface is not stable across feature versions of Python. The practical consequence is that C-extension libraries must be compiled for the new version. It may take some time before all your dependencies provide wheels compatible with the latest version.

From a safety point of view, you’re completely fine even if you’re not using the latest feature version. As you saw earlier, Python feature versions get regular bugfix updates for eighteen months and security fixes as needed for five years.

Still, you should have a plan for regularly updating your feature version. In particular, you should ensure that your versions don’t end up beyond end-of-life and unsupported.

You could, for instance, adopt a strategy where you stick to a feature version as long as it gets regular bugfix updates. You upgrade to the next version when it switches to only getting security fixes. Since bugfix releases are published for eighteen months, this would mean that you’d switch to a new feature version of Python about six months after its release.

Conclusion

Python’s bugfix releases don’t make a lot of headlines. While it’s true that most of the fun happens in feature releases, it’s also a good idea to pay attention to the low-profile regular updates. If you stay up to date with the latest releases of Python, you’ll know that your interpreter includes all the latest bug and security fixes.

In this tutorial, you’ve learned that you should update to the latest Python bugfix version. You’ve gotten to know about the difference between bugfix and feature versions and seen some strategies for how you can keep your projects up to date.

🐍 Python Tricks 💌

Get a short & sweet Python Trick delivered to your inbox every couple of days. No spam ever. Unsubscribe any time. Curated by the Real Python team.

Python Tricks Dictionary Merge

About Geir Arne Hjelle

Geir Arne is an avid Pythonista and a member of the Real Python tutorial team.

» More about Geir Arne

Each tutorial at Real Python is created by a team of developers so that it meets our high quality standards. The team members who worked on this tutorial are:

Master Real-World Python Skills With Unlimited Access to Real Python

Locked learning resources

Join us and get access to thousands of tutorials, hands-on video courses, and a community of expert Pythonistas:

Level Up Your Python Skills »

Master Real-World Python Skills
With Unlimited Access to Real Python

Locked learning resources

Join us and get access to thousands of tutorials, hands-on video courses, and a community of expert Pythonistas:

Level Up Your Python Skills »

What Do You Think?

Rate this article:

What’s your #1 takeaway or favorite thing you learned? How are you going to put your newfound skills to use? Leave a comment below and let us know.

Commenting Tips: The most useful comments are those written with the goal of learning from or helping out other students. Get tips for asking good questions and get answers to common questions in our support portal.


Looking for a real-time conversation? Visit the Real Python Community Chat or join the next “Office Hours” Live Q&A Session. Happy Pythoning!

Keep Learning

Related Topics: advanced best-practices devops