Revisited: Version Numbering in Python Package

In Version Numbering in Python Package I showed a way to store the package version number in the code. The method is in hindsight not exactly the best one (who knew!), so here is another try for simple projects.

Here I have

  • mypackage/ (the package directory)
  • mypackage/__init__.py
  • mypackage/version.py
  • setup.py

with contents:

mypackage/version.py:

__version__ = "1.2.3"

mypackage/__init__.py:

from .version import __version__
# plus whatever things my package actually offers or does

setup.py:

from pathlib import Path

from setuptools import setup


def get_version(pkg_name):
    version_filename = Path(__file__).parent / pkg_name / "version.py"
    with open(version_filename) as f:
        for line in f.readlines():
            if line.startswith("__version__"):
                sep = '"' if '"' in line else "'"
                return line.split(sep)[1]
    raise RuntimeError(f"Version not found in {version_filename}")


PACKAGE_NAME = "mypackage"

setup(
    name=PACKAGE_NAME,
    version=get_version(PACKAGE_NAME),
    description="My Package",
    packages=[PACKAGE_NAME],
)

What does it do?

  • It has the package name as a constant (PACKAGE_NAME) in setup.py
  • get_version() reads the version number from version.py

What are the benefits of this arrangement?

  • Version number is only stored in one place, and it is accessible runtime as mypackage.__version__
  • Package name is not repeated in setup.py
  • There is no package import in setup.py, which avoids certain problem situations (like, setup.py has install_requires list defined and the package imports those required packages; it will result in module import errors during the package install unless the required packages happen to be installed already)

After installing the package with “pip install .“:

(mypackagevenv) markku@btest:~$ pip list
Package       Version
------------- -------
mypackage     1.2.3
pip           20.3.3
pkg-resources 0.0.0
setuptools    40.8.0
wheel         0.36.2
(mypackagevenv) markku@btest:~$ python
Python 3.7.3 (default, Jul 25 2020, 13:03:44)
[GCC 8.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import mypackage
>>> mypackage.__version__
'1.2.3'
>>>

More ideas and information about storing the version numbers: Single-sourcing the package version (in packaging.python.org)

Updated: December 27, 2020 — 14:15

Leave a Reply