Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Adding version attribute to Python module

Tags:

python

I am building a Python module with a structure like:

mypackage/
    mypackage/
        __init__.py
        etc.py
    setup.py
    setup.cfg
    pyproject.toml

To build it, I am running $ python -m build. I noticed that version numbers weren't available (e.g. mypackage.__version__ is undefined after installing), and currently I am just setting it manually like:

setup.py

setup(..., version='0.0.1' )

pyproject.toml

[project]
version = '0.0.1'

I am new to Python package development and there are a few posts on this, but there does not seem to be a standard way of doing it.

The package is quite small and ideally I'd like to just update one thing like __version__ = '0.0.1' inside __init__.py, and then have this parsed automatically in setup.py and pyproject.toml.

like image 300
Adam Avatar asked Mar 06 '26 19:03

Adam


1 Answers

Do you really need/want a __version__ attribute at all?

Keeping a __version__ attribute available in the module namespace is a popular convention, but it's possibly falling out of fashion these days because stdlib importlib.metadata is no longer provisional. The one obvious place for a version string is in the package metadata, duplicating that same information in a module attribute may be considered unnecessary and redundant.

It also presents some conundrums for users when the version string exists in two different places - where should we look for it first, in the package metadata or in a module top-level namespace? And which one should we trust if the version information found in each of these places is different?

So, there is some benefit to only storing it in one place, and that place must be the package's metadata. This is because the Version field is a required field in the Core metadata specifications, but packages which opt-in to providing a __version__ attribute are just following a convention.

Getting/setting the version in package metadata

If you're using a modern build system, then you would specify the version string directly in pyproject.toml as described in PEP 621 – Storing project metadata in pyproject.toml. The way already shown in the question is correct:

[project]
name = "mypkg"
version = "0.0.1"

Users of mypkg could retrieve the version like so:

from importlib.metadata import version
version("mypkg")

Note that unlike accessing a __version__ attribute, this version is retrieved from the package metadata only, and the actual package doesn't even need to be imported. That's useful in some cases, e.g. packages which have import side-effects such as numpy, or the ability to retrieve versions of packages even if they have unsatisfied dependencies / complicated environment setup requirements.

What if you want access to the version number within the package itself?

Sometimes this is useful, for example to add a --version option to your command-line interface. But this doesn't imply you need a __version__ attribute hanging around, you can just retrieve the version from your own package metadata the same way:

parser = argparse.ArgumentParser(...)
...
parser.add_argument(
    "--version",
    action="version",
    version=importlib.metadata.version("mypkg"),
)
like image 115
wim Avatar answered Mar 09 '26 07:03

wim