Cross platform tool to find available python installations
Project description
ducktools: pythonfinder
Find local python installs on Windows/Linux/MacOS and find the latest installers from python.org for Windows and MacOS or sources for Linux (as python.org does not provide linux installers).
Requires Python >= 3.10 (but will discover older Python installs)
It is also available as an application and library on PyPI. The simplest way to install this is with uv.
With uv:
- Install it as an application with
uv tool install ducktools-pythonfinder - Run once with
uvx ducktools-pythonfinder - Add it as a library to a project with
uv add ducktools-pythonfinder - Add it as a library for a script with
uv add --script scriptname.py ducktools-pythonfinder - test it in a repl with
uv run --isolated --with ducktools-pythonfinder python
If you do not wish to use uv, you can also install as an application with
pipx, or manually manage dependencies in pyproject.toml,
inline script metadata
or in virtual environments using pip.
Command Line Usage
ducktools-pythonfinder can be used as a module or as a bundled zipapp (as pythonfinder.pyz).
python pythonfinder.pyz or python -m ducktools.pythonfinder
will provide a table of installed python versions
and their respective folders. It will also indicate the python running the
command if it is found, or the python that is the base for the venv running the command.
Python versions listed can be restricted by using the --max, --min and
--compatible options to the command. These roughly translate to >= for min, < for max
and ~= for compatible in python version specifiers.
If you wish to find the latest binaries available from python.org for your platform
(or sources on Linux) there is the additional online command with some extra flags.
By default it will fetch the latest patches for each Python release (eg: 2.7.18 for 2.7) for the hardware you're on. The filters for local versions also work.
--all-binarieswill get you all binary releases that match the restrictions.--systemand--machineallow you to specify a platform other than the one you are using (the values you give should match platform.system() and platform.machine() return values).--prereleaseincludes prerelease versions in the search.
Example:
python pythonfinder.pyz online --min 3.10 --system Windows --machine AMD64
| Python Version | URL |
| -------------- | ------------------------------------------------------------------ |
| 3.12.5 | https://www.python.org/ftp/python/3.12.5/python-3.12.5-amd64.exe |
| 3.11.9 | https://www.python.org/ftp/python/3.11.9/python-3.11.9-amd64.exe |
| 3.10.11 | https://www.python.org/ftp/python/3.10.11/python-3.10.11-amd64.exe |
Library Usage
Local installs
The module provides two main functions for searching for local python installs:
get_python_installsis a generator that will yield each python version it discoverslist_python_installswill take the python versions discovered byget_python_installsand return a sorted list from newest to oldest python version discovered.- For the purposes of sorting, prerelease versions are considered older than any released version.
On Windows these methods will search the registry for PEP514 recorded python installs
before checking for any pyenv-win installs that have not been registered. Finally, if
uv is available it will try to find Python installs managed by uv.
On Linux and MacOS this will search for pyenv installs first,
if uv is available it will then try to find uv managed python installs.
Finally it will search PATH for any other python* binaries that might be available.
If a python install is found twice (for instance a pyenv install in the windows registry) it will only be returned the first time it is found.
The python installs will be returned as instances of PythonInstall which will
contain version info and executable path along with some other useful metadata.
Example:
import os.path
from ducktools.pythonfinder import list_python_installs
user_path = os.path.expanduser("~")
for install in list_python_installs():
install.executable = install.executable.replace(user_path, "~")
print(install)
Example Windows Output:
PythonInstall(version=(3, 12, 5, 'final', 0), executable='~\\.pyenv\\pyenv-win\\versions\\3.12.5\\python.exe', architecture='64bit', implementation='cpython', metadata={'DiplayName': 'Python 3.12 (64-bit)', 'SupportUrl': 'https://github.com/pyenv-win/pyenv-win/issues', 'SysArchitecture': '64bit', 'SysVersion': '3.12', 'Version': '3.12.5', 'InWindowsRegistry': True}, shadowed=False)
PythonInstall(version=(3, 12, 3, 'final', 0), executable='~\\.pyenv\\pyenv-win\\versions\\3.12.3\\python.exe', architecture='64bit', implementation='cpython', metadata={}, shadowed=False)
PythonInstall(version=(3, 11, 9, 'final', 0), executable='~\\.pyenv\\pyenv-win\\versions\\3.11.9\\python.exe', architecture='64bit', implementation='cpython', metadata={'DiplayName': 'Python 3.11 (64-bit)', 'SupportUrl': 'https://github.com/pyenv-win/pyenv-win/issues', 'SysArchitecture': '64bit', 'SysVersion': '3.11', 'Version': '3.11.9', 'InWindowsRegistry': True}, shadowed=False)
PythonInstall(version=(3, 10, 11, 'final', 0), executable='~\\.pyenv\\pyenv-win\\versions\\3.10.11\\python.exe', architecture='64bit', implementation='cpython', metadata={'DiplayName': 'Python 3.10 (64-bit)', 'SupportUrl': 'https://github.com/pyenv-win/pyenv-win/issues', 'SysArchitecture': '64bit', 'SysVersion': '3.10', 'Version': '3.10.11', 'InWindowsRegistry': True}, shadowed=False)
PythonInstall(version=(3, 9, 13, 'final', 0), executable='~\\.pyenv\\pyenv-win\\versions\\3.9.13\\python.exe', architecture='64bit', implementation='cpython', metadata={'DiplayName': 'Python 3.9 (64-bit)', 'SupportUrl': 'https://github.com/pyenv-win/pyenv-win/issues', 'SysArchitecture': '64bit', 'SysVersion': '3.9', 'Version': '3.9.13', 'InWindowsRegistry': True}, shadowed=False)
PythonInstall(version=(3, 8, 10, 'final', 0), executable='~\\.pyenv\\pyenv-win\\versions\\3.8.10\\python.exe', architecture='64bit', implementation='cpython', metadata={'DiplayName': 'Python 3.8 (64-bit)', 'SupportUrl': 'https://github.com/pyenv-win/pyenv-win/issues', 'SysArchitecture': '64bit', 'SysVersion': '3.8', 'Version': '3.8.10', 'InWindowsRegistry': True}, shadowed=False)
PythonInstall(version=(3, 13, 0, 'candidate', 1), executable='~\\.pyenv\\pyenv-win\\versions\\3.13.0rc1\\python.exe', architecture='64bit', implementation='cpython', metadata={}, shadowed=False)```
Finding venvs
There is now a submodule to search for virtual environments.
from ducktools.pythonfinder.venv import list_python_venvs
for venv in list_python_venvs():
print(venv.executable)
Python.org search
Python.org searches are handled by the ducktools.pythonfinder.pythonorg_search module.
from packaging.specifiers import SpecifierSet
from ducktools.pythonfinder.pythonorg_search import PythonOrgSearch
# If system and machine are not provided this uses platform.system() and platform.machine()
searcher = PythonOrgSearch(system="Windows", machine="AMD64")
all_releases = searcher.releases
all_release_files = searcher.release_files
all_312_releases = searcher.matching_versions(SpecifierSet("~=3.12.0"))
all_312_downloads = searcher.matching_versions(SpecifierSet("~=3.12.0"))
all_312_311_win_binaries = searcher.all_matching_binaries(SpecifierSet(">=3.11.0, <3.13"))
latest_312_311_win_binaries = searcher.latest_minor_binaries(SpecifierSet(">=3.11.0, <3.13"))
latest_matching_win_binary = searcher.latest_binary_match(SpecifierSet(">=3.10"))
latest_prerelease_binary = searcher.latest_binary_match(SpecifierSet(">=3.10"), prereleases=True)
Why?
For the purposes of PEP723 script dependencies and other releated tools
it may be useful to find another version of python other than the one currently running
in order to satisfy the requires-python field.
This tool is intended to search for potential python installs to attempt to
satisfy such a requirement.
Isn't there already a 'pythonfinder' module?
That module appears to require searching for a specific version and will find venv pythons.
In contrast ducktools.pythonfinder simply yields python installs as they are discovered
and will attempt to avoid returning virtualenv python installs
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file ducktools_pythonfinder-0.10.4.tar.gz.
File metadata
- Download URL: ducktools_pythonfinder-0.10.4.tar.gz
- Upload date:
- Size: 223.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4bbcd5167581b78392d9a358fa12c3de9e3fbef8b51d54d835c33143566e34b1
|
|
| MD5 |
ff0546b0953e6de3b268778b7379b752
|
|
| BLAKE2b-256 |
705ff59741510b64f51c52bb76787f3f016a552513a833e30c1d722edee71e60
|
Provenance
The following attestation bundles were made for ducktools_pythonfinder-0.10.4.tar.gz:
Publisher:
publish_to_pypi.yml on DavidCEllis/ducktools-pythonfinder
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
ducktools_pythonfinder-0.10.4.tar.gz -
Subject digest:
4bbcd5167581b78392d9a358fa12c3de9e3fbef8b51d54d835c33143566e34b1 - Sigstore transparency entry: 652915128
- Sigstore integration time:
-
Permalink:
DavidCEllis/ducktools-pythonfinder@84552e523f73e284345e15925fd38ae6cc9c9017 -
Branch / Tag:
refs/tags/v0.10.4 - Owner: https://github.com/DavidCEllis
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish_to_pypi.yml@84552e523f73e284345e15925fd38ae6cc9c9017 -
Trigger Event:
release
-
Statement type:
File details
Details for the file ducktools_pythonfinder-0.10.4-py3-none-any.whl.
File metadata
- Download URL: ducktools_pythonfinder-0.10.4-py3-none-any.whl
- Upload date:
- Size: 37.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9af72d67afd3d95c4baf8c470c6250c2c16d971acecde23bb44059a4c340a42d
|
|
| MD5 |
1772f99c7e8f40f5d1ee88658af44167
|
|
| BLAKE2b-256 |
af74785c698e5c3e81e08bf8d6a453e4008bececb1437f7b3bb623b33e2d9ae5
|
Provenance
The following attestation bundles were made for ducktools_pythonfinder-0.10.4-py3-none-any.whl:
Publisher:
publish_to_pypi.yml on DavidCEllis/ducktools-pythonfinder
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
ducktools_pythonfinder-0.10.4-py3-none-any.whl -
Subject digest:
9af72d67afd3d95c4baf8c470c6250c2c16d971acecde23bb44059a4c340a42d - Sigstore transparency entry: 652915137
- Sigstore integration time:
-
Permalink:
DavidCEllis/ducktools-pythonfinder@84552e523f73e284345e15925fd38ae6cc9c9017 -
Branch / Tag:
refs/tags/v0.10.4 - Owner: https://github.com/DavidCEllis
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish_to_pypi.yml@84552e523f73e284345e15925fd38ae6cc9c9017 -
Trigger Event:
release
-
Statement type: