packaging
raw JSON → 26.0 verified Tue May 12 auth: no python install: verified quickstart: verified
Reusable core utilities for Python packaging interoperability specifications. Implements PEP 440 version handling, specifiers, markers, requirements, tags, metadata, and lockfiles. Used internally by pip, setuptools, and most build tools. Uses calendar-based versioning (YY.N). Current version is 26.0 (2026).
pip install packaging Common errors
error ModuleNotFoundError: No module named 'packaging' ↓
cause The 'packaging' library is not installed in your current Python environment.
fix
pip install packaging
error packaging.version.InvalidVersion: Invalid version: '...' (e.g., 'Invalid version: 'french toast'') ↓
cause The version string provided does not conform to the PEP 440 versioning scheme, which the 'packaging' library strictly enforces.
fix
Ensure the version string follows PEP 440 (e.g., '1.0', '1.0.post1', '1.0a1') or handle non-compliant versions gracefully in your code.
error AttributeError: module 'packaging.version' has no attribute 'LegacyVersion' ↓
cause The 'LegacyVersion' class was removed in 'packaging' version 22.0. This error occurs when older code or dependencies attempt to access it with a newer 'packaging' installation.
fix
Downgrade the 'packaging' library to a compatible version (e.g.,
pip install 'packaging<22.0') or update the dependent code to use packaging.version.Version and handle non-PEP 440 versions appropriately without LegacyVersion. error packaging.requirements.InvalidRequirement: Parse error at "': ...'": Expected stringEnd ↓
cause The requirement string provided to `packaging.requirements.Requirement` is malformed and does not adhere to the PEP 508 specification for dependency specifiers.
fix
Correct the requirement string syntax. Ensure it follows the format 'package_name[extra] (specifier); marker', for example, 'my-package[test]>=1.0; python_version < "3.9"'.
error packaging.specifiers.InvalidSpecifier: Invalid specifier: '...' (e.g., 'Invalid specifier: 'lolwat'') ↓
cause The specifier string provided to `packaging.specifiers.Specifier` or `SpecifierSet` is syntactically incorrect and does not conform to PEP 440's specifier format.
fix
Provide a valid version specifier string, such as '==1.0', '>=1.0,<2.0', '~=1.0.0', or '!=1.1'.
Warnings
breaking LegacyVersion and LegacySpecifier were removed in 22.0. packaging.version.parse() now raises InvalidVersion for non-PEP 440 version strings instead of silently returning a LegacyVersion object. ↓
fix Wrap Version() / parse() calls in a try/except InvalidVersion block. Migrate any non-PEP 440 version strings to compliant ones.
breaking SpecifierSet and Specifier were moved from packaging.version to packaging.specifiers in an early release. Importing from packaging.version will fail. ↓
fix Use: from packaging.specifiers import SpecifierSet, Specifier
breaking Optional metadata.Metadata attributes now default to None (changed in 24.0). Code checking for empty-string defaults will silently mishandle absent fields. ↓
fix Guard attribute access with `if metadata.summary is not None` rather than truthiness checks.
gotcha SpecifierSet.filter() and Specifier.contains() exclude pre-releases by default unless the specifier itself includes a pre-release version. Pass prereleases=True explicitly to include them. ↓
fix spec.filter(versions, prereleases=True) or SpecifierSet('>=1.0', prereleases=True)
gotcha canonicalize_name() returns a NormalizedName (typing.NewType of str). Mixing raw strings and NormalizedName values causes mypy errors. Always canonicalize before comparing package names. ↓
fix Compare only after canonicalization: canonicalize_name(a) == canonicalize_name(b)
gotcha The library uses calendar versioning (YY.N), not semver. There is no reliable way to determine whether a release contains breaking changes from the version number alone. ↓
fix Pin to an exact version in production tooling, e.g. packaging==26.0, and review the changelog on each upgrade.
gotcha packaging has no runtime dependencies since 21.0 (pyparsing was removed and replaced with a hand-written parser). Do not add pyparsing as a workaround for older compatibility issues. ↓
fix No extra dependencies needed. Just pip install packaging.
Install compatibility verified last tested: 2026-05-12
python os / libc status wheel install import disk
3.10 alpine (musl) - - 0.01s 18.3M
3.10 slim (glibc) - - 0.01s 19M
3.11 alpine (musl) - - 0.04s 20.2M
3.11 slim (glibc) - - 0.03s 21M
3.12 alpine (musl) - - 0.03s 12.1M
3.12 slim (glibc) - - 0.03s 13M
3.13 alpine (musl) - - 0.06s 11.7M
3.13 slim (glibc) - - 0.06s 12M
3.9 alpine (musl) - - 0.01s 17.8M
3.9 slim (glibc) - - 0.01s 18M
Imports
- Version wrong
from packaging.version import LegacyVersioncorrectfrom packaging.version import Version - parse wrong
v = parse('1.0'); type(v) == LegacyVersioncorrectfrom packaging.version import Version, parse - SpecifierSet wrong
from packaging.version import SpecifierSetcorrectfrom packaging.specifiers import SpecifierSet - Requirement
from packaging.requirements import Requirement - canonicalize_name
from packaging.utils import canonicalize_name - Marker
from packaging.markers import Marker
Quickstart verified last tested: 2026-04-23
from packaging.version import Version
from packaging.specifiers import SpecifierSet
from packaging.requirements import Requirement
from packaging.utils import canonicalize_name
# Parse and compare PEP 440 versions
v = Version('1.2.3')
print(v.major, v.minor, v.micro) # 1 2 3
print(v.is_prerelease) # False
# Check if a version satisfies a specifier
spec = SpecifierSet('>=1.0,<2.0')
print(v in spec) # True
# Parse a PEP 508 requirement string
req = Requirement('requests[security]>=2.28; python_version>="3.8"')
print(req.name) # requests
print(req.extras) # {'security'}
print(req.specifier) # >=2.28
print(req.marker) # python_version >= "3.8"
# Normalize a package name (PEP 503)
print(canonicalize_name('Django')) # django
print(canonicalize_name('oslo.concurrency')) # oslo-concurrency