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)