Explain Codes LogoExplain Codes Logo

Standard way to embed version into Python package?

python
versioning
semantic-versioning
package-management
Anton ShumikhinbyAnton Shumikhin·Mar 7, 2025
TLDR

Integrate a version number into your Python package by assigning __version__ in your package's __init__.py. Adhere to the semantic versioning format (MAJOR.MINOR.PATCH). Example:

# Inside your package's __init__.py __version__ = '1.0.0' # Versioning: now easier than choosing a Python script name

Access it using:

# Retrieve package version from your_package import __version__ print(__version__) # Prints version so you don't have to

Utilizing this versioning strategy is key for healthy dependency management and sustaining upgrade sanity across subsequent roll-outs of your package.

Versioning 101: The Essentials

The PEP triumvirate

Embarking on a Python project? Let the "PEP triumvirate" be your stead. PEP 440 offers clear guidelines on version format compliance, PEP 396 champions the use of __version__, while PEP 8 emphasizes the ideal placement of module-level "dunder" names.

The single source of truth

All for one, one for all! Prefer storing your version info in _version.py file located in the package directory - the one-stop source for versioning.

Universal version format

Adhere to semantic versioning with a string for __version__; it's crystal clear and aligns with PEP 440, making it universally compatible.

Synchronized versions

Ensure harmonious synchronization between setup.py and _version.py. Tip: Avoid importing the package directly into your setup.py, instead, fetch version info using regex:

# Inside your setup.py import re with open("your_package/_version.py", "rt") as fh: version = re.search(r"__version__ = '([^']+)'", fh.read()).group(1) # Package regex practitioner - a title worth bragging at your local Python meetup

Automated versioning

Never underestimate a developer's love for automation! Tools like python-versioneer or pbr automate version management tied to git tags - goodbye manual updates!

Visualising versioning: A postal analogy

Think of versioning like the postal system:

Your package: A letter ready to be mailed 📨
__version__ = '1.0.0' # Stamp of approval, postal workers (users) rejoice!
Package delivery: The recipient instantly knows details of the version delivered: 📨→ 🏷️ `Version: 1.0.0` It's transparent, simple and consistent. Just like your morning coffee ☕️.

Consistent retrieval

Promote uniformity by following __version__ universal terminology, keeping parity between standard libraries and 3rd-party modules.

Quick and efficient comparison

Prefer tuples of integers to enable easy version comparisons when in code.

Mitigating build-time snafus

In setup.py, dodge importing your package. Not only does it ward off side effects during installation, but it also prevents any tantrums during the build process.