To run Python code you need to ... 1. Choose the appropriate/best language version 2. Find/install an interpreter to meet that language version need 3. Create a virtual environment that uses the selected interpreter 4. Install the code's dependencies 5. Run the code # Goals - [ ] Easiest way to [[#`py launch`|launch an interpreter]] - [x] Select the newest version - [x] Specify the version - [ ] Support the major OSs - [x] Linux - [x] macOS - [ ] [[#Windows support]] - [ ] Registry - [ ] Microsoft Store - [x] From a virtual environment - [ ] Install an interpreter (requires [[Relocatable builds]]) - [ ] [[Virtual environment location]] - [ ] [Inline script metadata](https://packaging.python.org/en/latest/specifications/inline-script-metadata/) for `requires-python` only? - [ ] Easiest way to [[#`py list`|list interpreters]] - [ ] Fancy/human-readable - [ ] JSONL - [ ] Easiest way to [[#`py run`|run code]] 🏃 - [ ] [Inline script metadata](https://packaging.python.org/en/latest/specifications/inline-script-metadata/) - [ ] [[requires-python spec]] - [ ] `.py` files - [ ] Path - [ ] URL - [ ] Directories via `__main__.py`? - [ ] Zip files via `__main__.py`? - [ ] `pylock.toml` (takes care of interpreter selection and virtual environment creation, even if you do specify config details) - [ ] Scripts next to `pylock.toml`? - [ ] Directories w/ `__main__.py`? - [ ] Modules (`-m`) based on cwd? - [ ] `bin/` based on cwd? - [ ] Zip file? - [ ] `pyproject.toml` (takes care of interpreter selection and virtual environment creation, even if you do specify config details) - [ ] Write out lock file? - [ ] Scripts? - [ ] Directories w/ `__main__.py`? - [ ] Modules (`-m`) based on cwd? - [ ] Zip file? - [ ] `bin/` based on cwd? - [ ] Install Python on demand (requires [[Relocatable builds]]) - [ ] `py x` shorthand (like from `chmod`, plus nod to pipx)? - [ ] `venv` + `sync` for more manual control while keeping installation of packages simple (requires way to launch interpreter only) - [ ] Easiest way to [[#`py tool`|run tools]] 🧰 - [ ] Install - [ ] Run (`py x`?) # Ideas ## Subcommands [Proposal for user-contributed subcommands](https://github.com/brettcannon/python-launcher/discussions/222) - Make each command a feature of the crate to control what commands are available? - Complex commands should decompose to other commands ### `py launch` - [`pymanager exec`](https://peps.python.org/pep-0773/#exec-subcommand) Same as bare `py` in terms of semantics/purpose (or skip and push people towards [[#`py run`]]?). Workflow tools do not have an equivalent command. Everyone else has their `run` command execute the command as found in the virtual environment if a path is not provided, i.e. `run python`. - `--version`/`--python`: specify the Python version, much like e.g. `-3.12` - `uv` uses `--python` - `--ignore-venv`/`--exclude-venv`/`--skip-venv`: exclude virtual environments from the list of potential interpreters - `--`: All flags following are passed on to the interpreter - Used by [`uv run`](https://docs.astral.sh/uv/reference/cli/#uv-run) - `-m`: Equivalent to `-m` to the interpreter - Pragmatic shortcut to minimize need to specify `--` for the `-m` common case - Argument parsing stops once a path, `-m`, or `--` is found ### `py run` - [`pdm run`](https://pdm-project.org/en/latest/reference/cli/#run) - [`poetry run`](https://python-poetry.org/docs/cli/#run) - [`hatch run`](https://hatch.pypa.io/latest/cli/reference/#hatch-run) - [`uv run`](https://docs.astral.sh/uv/reference/cli/#uv-run) - [`pipx run`](https://pipx.pypa.io/latest/docs/#pipx-run) For simplest way to execute code in an implicit virtual environment (i.e. the Python interpreter is an implementation detail). Need to consider [[Caching app files while being ignored by backup apps]] for the implicit virtual environments. - `--group`/`--with`: Specifies the dependency group to use (only applicable when a directory path is specified, maybe zip file if it ships with a `pyproject.toml`) - Care about extras, e.g. `--extra` or implicitly specified via `--group`? - `uv` uses `--extra` - If a file path is specified: - If the file is a zip file, do anything special like look for inline script metadata in `__main__.py`? - If [inline script metadata](https://packaging.python.org/en/latest/specifications/inline-script-metadata/) is specified, use that - Otherwise assume metadata of no dependencies and any Python version - If a directory path is specified: - For convenience when a [directory contains a `__main__.py` file](https://docs.python.org/3/using/cmdline.html) - Use inline script metadata or `pyproject.toml`? - Provide a way to specify whether `launch` or `run` are the default when no subcommand specified? - Don't read the shebang; only rely on the metadata to limit the Python version - Execute what's in `bin/` for the virtual environment if command name is specified? ### `py list` - [`hatch python show`](https://hatch.pypa.io/latest/cli/reference/#hatch-python-show) - [`pdm python list`](https://pdm-project.org/en/latest/reference/cli/#list_2) - [`uv python list`](https://docs.astral.sh/uv/reference/cli/#uv-python-list) - [`pipx interpreter list`](https://pipx.pypa.io/latest/docs/#pipx-interpreter) - [`pymanager list`](https://peps.python.org/pep-0773/#list-subcommand) List all of the discovered interpreters. - [Discourse discussion](https://discuss.python.org/t/what-information-is-useful-to-know-statically-about-an-interpreter/25563) - [PEP 711 cross-post](https://discuss.python.org/t/pep-711-pybi-a-standard-format-for-distributing-python-binaries/25547/14?u=brettcannon) - `--format`: Specify the output format; all output in UTF-8 - `jsonl`: Print [interpreter details](https://github.com/brettcannon/python-launcher/discussions/168) using [JSON Lines](https://jsonlines.org/) - This should work with [`json -o` for Nu](https://www.nushell.sh/commands/docs/from_json.html) - Results are streamed as results are found instead of being sorted - Fields - `path` - `virtual` - `found via` - `$VIRTUAL_ENV` - `.venv` - `$PATH` - `pretty` (default): Print interpreter details in a format designed to be human-readable - Include same details as the JSONL output - Sorted by how "good" the interpreter is - `--ignore-venv`: Ignore virtual environments (or default to `--include-venv`) - Might be unnecessary or only useful via `--one` - `--one` - Only print the path to the "best" interpreter - https://github.com/python/cpython/issues/102522 would give more accurate version info for virtual environments ### `py venv` - [`pdm venv`](https://pdm-project.org/latest/reference/cli/#venv) Requires [[Virtual environment location]] landing. - Create a virtual environment in `.venv` next to `pyproject.toml` (this should be the same as what `py run` would do if it was pointed at a project to create a virtual environment) - Without pip, but that might require a `py pip` command or some other abstraction over installation of dependencies - Provide a way to get the location of the virtual environment, else error out? - Provide a way to point to a preexisting or already active virtual environment? - Provide the command to source to activate the virtual environment? ### `py completions` - [`pdm completion`](https://pdm-project.org/latest/reference/cli/#completion) Print the completion script for the specified shell. It would be a command instead of a static file so that it can be accurate for what interpreters are installed. But if the shells provide a way to do it dynamically then this might not be worth it. ### `py tool` - [`pipx run`](https://pipx.pypa.io/latest/docs/#pipx-run) - [`uv tool`](https://docs.astral.sh/uv/reference/cli/#uv-tool) Install and/or run tools from e.g. PyPI. Trickiest bit is the UI for installing versus running such that running is very short when you don't want to bother installing (`py x`?). ### `py sync` - [`pdm sync`](https://pdm-project.org/latest/reference/cli/#sync) - [`uv sync`](https://docs.astral.sh/uv/reference/cli/#uv-sync) - [`poetry sync`](https://python-poetry.org/docs/cli/#sync) - [Hatch syncs the environments automatically](https://hatch.pypa.io/latest/environment/#dependencies) whenever you run a command Create/guarantee the virtual environment has the appropriate packages installed. ### `py python` - [pymanager install](https://peps.python.org/pep-0773/#install-subcommand) - [`uv python`](https://docs.astral.sh/uv/reference/cli/#uv-python) - [`poetry python`](https://python-poetry.org/docs/cli/#python) - [`hatch python`](https://hatch.pypa.io/latest/cli/reference/#hatch-python) - [`pdm python`](https://pdm-project.org/latest/reference/cli/#python) ([`pdm py`](https://pdm-project.org/latest/reference/cli/#py)) Install/manage Python interpreters. - Worry about anything other than CPython? - PyPy? - Any builds other than the native CPU? - WASI? ## Library crates Wait until after any `py install` command happens and seeing if relocatable builds could be used to create a Python Launcher written in Python. - Create `locatepython` crate (or `findpython`), based around JSON schema - Add Windows support - Share across `py`, PVSC, and `uv` - Shebang reading? - Inline metadata parsing? - `requires-python` handling? - Cached pip handling? ## Windows support - [Virtual environments](https://github.com/brettcannon/python-launcher/issues/57) - [`PATH`](https://github.com/brettcannon/python-launcher/issues/14) - [Registry](https://github.com/brettcannon/python-launcher/issues/15) - [Microsoft Store](https://github.com/brettcannon/python-launcher/issues/16)