bin+lib python-launcher

The Python launcher for UNIX

10 releases (6 breaking)

✓ Uses Rust 2018 edition

0.7.2 Mar 29, 2019
0.7.1 Mar 17, 2019
0.6.1 Mar 8, 2019
0.5.0 Nov 25, 2018
0.1.0 Jun 2, 2018

#264 in Command line utilities

Download history 7/week @ 2019-07-31 23/week @ 2019-08-07 181/week @ 2019-08-21 23/week @ 2019-08-28 35/week @ 2019-09-04 14/week @ 2019-09-11 28/week @ 2019-09-18 21/week @ 2019-09-25 16/week @ 2019-10-02 1/week @ 2019-10-09 40/week @ 2019-10-16 11/week @ 2019-10-23 21/week @ 2019-10-30

115 downloads per month

MIT license

718 lines

The Python Launcher for UNIX

An implementation of the py command for UNIX-based platforms.

The goal is to have py become the cross-platform command that all Python users use when executing a Python interpreter. By having a version-agnostic command it side-steps the "what should the python command point to?" debate by clearly specifying that upfront (i.e. the newest version of Python that is installed). This also unifies the suggested command to document for launching Python on both Windows as UNIX as py which has existed as the preferred command on Windows for some time.

See the top of py --help for instructions.

Search order

Please note that while searching, the search for a Python version can become more specific. This leads to a switch in the search algorithm to the one most appropriate to the specificity of the version.

py -3.6 (specific version)

  1. Search PATH for python3.6

py -3 (loose/major version)

  1. Use the version found in the PY_PYTHON3 environment variable if defined (e.g. PY_PYTHON3=3.6)
  2. Search PATH for all instances of python3.Y
  3. Find the executable with largest Y that earliest on PATH

py (any/unknown version)

  1. Use ${VIRTUAL_ENV}/bin/python immediately if available
  2. If the first argument is a file path ...
    1. Check for a shebang
    2. If executable starts with /usr/bin/python, /usr/local/bin/python, /usr/bin/env python or python, proceed based on the version found (bare python is considered python2 for backwards-compatibility)
  3. Use the version found in the PY_PYTHON environment variable if defined (e.g. PY_PYTHON=3 or PY_PYTHON=3.6)
  4. Search PATH for all instances of pythonX.Y
  5. Find the executable with the largest X.Y earliest on PATH


NOTE: I am using this project to learn Rust, so please don't be offended if I choose to implement something myself instead of accepting a pull request that you submit. (Pull requests to do something I have already implemented in a more idiomatic fashion are very much appreciated, though.)

PEP 397: Python launcher for Windows (documentation)


  1. Keep environment variable naming?
  • No other Python env vars are prefixed with PY_ (it's always PYTHON)
  • The PY_PYTHON aspect feels redundant
  1. Configuration files
  • Customized commands?
  • Want a better format like TOML?
  • Probably want a way to override/specify things, e.g. wanting a framework build on macOS somehow
    • Aliasing? E.g. 2.7-framework for /System/Library/Frameworks/Python.framework/Versions/2.7/Resources/Python.app/Contents/MacOS/Python?
    • Just provide a way to specify a specific interpreter for a specific version? E.g. 2.7 for /System/Library/Frameworks/Python.framework/Versions/2.7/Resources/Python.app/Contents/MacOS/Python
    • What about implementations that don't install to e.g. python3.7 like pypy3?
  • How should config file search work?
  1. Windows support
  • Registry
  • PATH
  • Read ../pyvenv.cfg to resolve for Any version
    • Acts as a heavyweight "symlink" to the Python executable for the virtual environment
    • Speeds up environment creation by not having to copy over entire Python installation (e.g. .pyd files)
  1. Provide a pylauncher package (it will make the pipenv developers happy 😃; might change name to pyfinder for package)
  2. Use OsString/OsStr everywhere (versus now which is wherever it's easy w/ path::Path)?
    • Widest compatibility for people where they have undecodable paths (which is hopefully a very small minority)
    • Massive pain to make work (e.g. cannot easily convert to a CString)


  1. Have --list somehow denote activated virtual environment?
    • What does the Windows launcher do in this case?
    • Slight pain as there's no way to no the version of Python w/o executing it to query its version as virtual environments has no major.minor-named executable
  2. Provide a helpful error message based on requested version when no interpreter found
  3. Start using human-panic
  4. Man page?


  1. Split up lib.rs into separate files
  2. Pare down public exposure of functions
  3. Consider having functions take arguments instead of querying environment (i.e. don't directly query PATH, VIRTUAL_ENV to ease testability)
    • Can provide functions or constants to minimize typos in querying environment
  4. Go through functions to adjust for returning Option versus Result (e.g. split_shebang(),version_from_flag(), choose_executable()`)
  5. Consider dropping nix dependency for a straight libc dependency (to potentially make Debian packaging easier)


~18K SLoC