mrkeyoor.com_
Thu 06 Aug 01:00 UTC
PyPIInfraupdated 05 Aug 2026

distro

distro answers one question: which OS distribution is this Python process running on? It reads /etc/os-release (falling back to lsb_release output, distro release files, and uname on BSD) and gives you a stable machine-readable id like "ubuntu" or "rhel", version numbers, codenames, and the ID_LIKE chain, plus a small CLI. It exists because platform.linux_distribution() was removed from the standard library in Python 3.8, and it became the drop-in replacement that pip, Ansible-adjacent tooling, and countless installers depend on.

Verdict

The correct answer when you must know the Linux distribution on Python versions or edge cases the stdlib does not cover, and a dependency you will inherit through pip anyway. On Python 3.10+ with simple needs, platform.freedesktop_os_release() does the job without adding a package.

API stability5/5The module-level API (id, name, version, like, info) has been effectively frozen for years; 1.x since 2016-era lineage and nothing about the problem domain forces breaking changes.
Docs4/5distro.readthedocs.io documents every function with data-source precedence explained, and the README is clear; there is just not much narrative guidance on the messy real-world os-release edge cases.
Maintenance3/5Repo pushed July 2026 and only 13 open issues and PRs, but the last release was December 2023 and the planned Windows/macOS support has been an open issue for years; stable but close to dormant.
Ecosystem5/5Roughly 97M weekly downloads because pip itself and much of the packaging and devops toolchain depend on it; it is packaged natively by Debian, Fedora, Arch, and the rest.

Use it if

  • You branch install or config logic on the distribution: distro.id() returning "debian", "fedora", or "alpine" is exactly the switch value you need
  • You need family matching, not exact matching: distro.like() exposes ID_LIKE so Linux Mint can be treated as "ubuntu debian" without an ever-growing if-chain
  • You report environment info in diagnostics or telemetry and want one call (distro.info() or the distro CLI) that behaves the same across Linux and BSD
  • You still support Python below 3.10 and need os-release parsing that works there
Skip it if

Setup reality

pip install distro is as easy as it gets: pure Python, no dependencies, supports Python 3.7+ (current release requires 3.6+ per metadata, tests target 3.7+ and PyPy). It is even documented as safe to vendor by copying distro.py into your project. The gotchas are environmental, not install-time: results depend entirely on the host's /etc/os-release quality, minimal containers can lack lsb_release so fallback data like codenames may be empty, and calling it on Windows or macOS quietly yields empty strings rather than an error, which surprises people writing cross-platform checks.

Patterns

Get the machine-readable distribution IDget-distro-id

import distro

print(distro.id())  # 'ubuntu', 'rhel', 'alpine', 'arch', ...

IDs are normalized and stable (rhel, not Red Hat Enterprise Linux); on non-Linux/BSD platforms this returns an empty string, not an exception.

Get a pretty name for displayhuman-readable-name

import distro

print(distro.name(pretty=True))  # 'Ubuntu 24.04.2 LTS'
print(distro.name())             # 'Ubuntu'

pretty=True includes version and codename when the distribution provides them; use this for logs and bug reports, never for branching logic.

Get the most precise version availablebest-version

import distro

print(distro.version())           # '24.04'
print(distro.version(best=True))  # '24.04.2'

best=True scans all data sources for the most detailed number instead of respecting source precedence; the two calls can disagree, so pick one convention and stick to it.

Compare against a minimum versionversion-parts

import distro

major, minor, build = distro.version_parts(best=True)
if distro.id() == "ubuntu" and int(major) >= 22:
    enable_modern_path()

Parts come back as strings and may be empty on rolling-release distros like Arch, so guard the int() conversion.

Match distribution families via ID_LIKEfamily-matching

import distro

DEBIAN_FAMILY = {"debian", "ubuntu"}
ids = {distro.id(), *distro.like().split()}
if ids & DEBIAN_FAMILY:
    use_apt()
elif ids & {"rhel", "fedora", "centos"}:
    use_dnf()

distro.like() returns a space-separated string (possibly empty), so derivatives like Mint ('ubuntu debian') or Rocky ('rhel centos fedora') match without enumerating every fork.

Collect everything for diagnosticsfull-info-dict

import distro

info = distro.info(pretty=False, best=True)
# {'id': 'ubuntu', 'version': '24.04.2', 'version_parts': {...},
#  'like': 'debian', 'codename': 'noble'}
report["os"] = info

info() is JSON-serializable as-is, which makes it the one-liner for attaching environment context to error reports.

Get the release codename for repo URLscodename

import distro

codename = distro.codename()  # 'noble', 'bookworm', ...
repo_line = f"deb https://example.com/apt {codename} main"

Codename can be an empty string on distros without one (Fedora, Arch) and sometimes requires lsb_release to be installed; always handle the empty case.

Read a raw os-release attributeraw-os-release-field

import distro

print(distro.os_release_attr("id_like"))         # 'debian'
print(distro.os_release_attr("version_codename")) # 'noble'
print(distro.os_release_attr("variant_id"))       # e.g. 'workstation'

Attribute names are the lowercased os-release keys; this is the escape hatch for fields the high-level API does not expose, like VARIANT_ID or BUILD_ID.

Use the CLI in shell scriptscli-usage

$ distro
Name: Ubuntu 24.04.2 LTS
Version: 24.04.2
Codename: noble

$ distro -j | jq -r .id
ubuntu

The console script installs with the package; python -m distro works too and is safer inside virtualenvs that are not on PATH.

Vendor distro.py without adding a dependencyvendor-single-file

# In your project, no pip install:
$ curl -O https://raw.githubusercontent.com/python-distro/distro/master/src/distro/distro.py

# then in code
from . import distro
print(distro.id())

Vendoring is explicitly supported by the project; installers and bootstrap scripts use this to detect the OS before any package manager is available.

Prefer stdlib on 3.10+, fall back to distrostdlib-fallback

import platform

try:
    os_release = platform.freedesktop_os_release()
    distro_id = os_release.get("ID", "")
except (AttributeError, OSError):
    import distro
    distro_id = distro.id()

platform.freedesktop_os_release() only reads os-release files; distro additionally falls back to lsb_release, release files, and uname, so keep it for old or odd hosts.

Alternatives

PackageRegistryPick it when
psutilPyPIYou need system facts beyond the distro name: CPU, memory, disks, processes, boot time.
distro-infoPyPIYou specifically need Debian and Ubuntu release metadata such as EOL dates and supported series, not host detection.