Before you write a build matrix, ask py3versions what Debian thinks is default, supported and installed. It also checks a version constraint straight out of a Debian control file. Every command here is read-only. Allow about ten minutes, with the python3-minimal package installed and a shell handy.
This guide was checked against Ubuntu's python3-minimal package version 3.12.3-0ubuntu2.1, with the command at /usr/bin/py3versions. The version list is distribution data, so your own output will shift as Ubuntu's Python policy shifts.
Start with ordinary, unprivileged checks. Nothing here installs anything or needs sudo:
$ command -v py3versions
/usr/bin/py3versions
$ dpkg-query -W -f='${Package} ${Version}\n' python3-minimal
python3-minimal 3.12.3-0ubuntu2.1
This reports Debian's packaging view of Python versions. It is not a general interpreter finder, and it will not list every Python binary that happens to sit on PATH.
Checkpoint: if command -v finds nothing, stop and repair the package through your normal package-management process rather than copying a script from another machine.
Ask for the default runtime, then the full supported list:
$ py3versions --default
python3.12
$ py3versions --supported
python3.12
--supported prints them ascending and puts the default last. Do not assume the last item in a generic sorted list is the default; use --default for that.-d and -s work the same as the long flags, which read better in scripts and documentation./usr/bin/python3 default link.--installed narrows the answer to supported interpreters that are actually present:
$ py3versions --installed
python3.12
$ py3versions --min-supported
python3.12
$ py3versions --max-supported
python3.12
Minimum and maximum describe the supported set, not the oldest and newest binary a filesystem scan happens to turn up. That distinction stops a retired interpreter from getting mistaken for a legitimate build target.
Reach for --version, or -v, when something else needs bare version numbers without the python prefix:
$ py3versions --supported --version
3.12
$ py3versions --installed --version
3.12
Checkpoint: for a build matrix, compare --supported against --installed. A supported version that is missing from installed is a packaging or host-coverage decision, not automatically a broken Python setup.
Debian source packages can carry an X-Python3-Version field in the Source: section of debian/control. Pass either the raw field value or a control-file path to --requested. This example uses a temporary file, so no real package metadata is touched:
$ control_file=$(mktemp /tmp/example-control.XXXXXX)
$ printf '%s\n' 'Source: example-package' 'X-Python3-Version: >= 3.10, << 3.13' '' 'Package: example-package' > "$control_file"
$ py3versions --requested "$control_file"
python3.12
$ py3versions --requested '>= 3.10, << 3.13' --version
3.12
The syntax accepts an exact minor version, or a lower and upper bound. The installed implementation ignores Python 2 versions entirely, along with the keywords all, current and current_ext. It returns only versions that are both requested and supported, in the same order as --supported.
That mktemp call is the only state change here, all under /tmp. Remove it afterwards using the exact path mktemp printed, not a broad wildcard.
For a source tree, point the command straight at its actual metadata:
$ py3versions --requested debian/control
python3.12
The command reads the source section. If the field is absent, the documented fallback is the supported Python 3 list after checking debian/control. A malformed value, a file that is not a control file, or a constraint matching no supported version all produce an error and a non-zero exit status.
Calling --requested with no argument is not a way to ask for the default; use --default for that. Keep the two questions separate: requested versions come from package metadata, the default comes from the system's own Python configuration.
Capture the exit status when a failed version check needs to stop a build. Do not treat an empty variable as a success:
requested=$(py3versions --requested debian/control --version) || {
printf '%s\n' 'X-Python3-Version could not be resolved' >&2
exit 1
}
printf 'supported requested versions: %s\n' "$requested"
Nothing in this workflow needs elevated privileges. Do not run it under sudo unless your source tree or control file has deliberately restricted permissions; privilege cannot fix malformed metadata or make an unsupported Python version supported.
py3versions path and package version.--version came out only when a caller wanted numbers without the prefix.X-Python3-Version without editing real package metadata.