Version Numbering in Python Package

After written the short Python package post I realized that the version number (actually string but anyway) of the package is now in two different places: in the package code (__init__.py) and in the package install metadata (setup.py). Obviously that’s not ideal, so I tried to figure out a way to define the version in only one place, and here’s my attempt.

First, in the same directory as the package code, create _version.py with the following contents:

__version__ = "1.2.dev1"

(For the version numbering scheme, see PEP 440 — Version Identification and Dependency Specification.)

Then modify the package code in __init__.py:

from ._version import __version__ as _version
__version__ = _version

def get_stuff():
    return "This is stuff. Use it wisely."

Finally, recreate setup.py:

from setuptools import setup, find_packages
from stuff._version import __version__

setup(
        name="stuff",
        version=__version__,
        description="The Stuff package by Me",
        packages=find_packages(),
    )

This way the version number is specified in only one file (_version.py). Here is how the module usage looks like:

$ python3
Python 3.7.3 (default, Apr  3 2019, 05:39:12)
[GCC 8.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import stuff
>>> stuff.__version__
'1.2.dev1'
>>> stuff.get_stuff()
'This is stuff. Use it wisely.'
>>> 

Now, the package name (stuff) is still mentioned twice in setup.py: once in version information import and once in the name argument for the setup function. They can be handled in setup.py also like this:

from setuptools import setup, find_packages
from importlib import import_module

PKG_NAME = "stuff"

module = import_module("{}._version".format(PKG_NAME))
setup(
        name=PKG_NAME,
        version=module.__version__
        description="The Stuff package by Me",
        packages=find_packages(),
    )

Extra:

If you need to compare version strings, you can do it like this:

from distutils.version import LooseVersion as version
import stuff

if version(stuff.__version__) < version("1.3"):
    print("Sorry, I need at least version 1.3 of stuff")

Updated: June 29, 2019 — 20:15

Leave a Reply