PythonUp — The Python Runtime Manager (POSIX)
PythonUp helps your install and manage Python runtimes on your computer. This is the POSIX version.
Windows user? Check out PythonUp-Windows.
This is a work in progress. You are welcomed to try it, and I’ll try to resolve any problems you have using it. I’m still experimenting much of the internals, however, so anything can break when you upgrade without backward-compatibility in mind.
PythonUp for POSIX is officially distributed with Homebrew. Install it with:
brew install --HEAD uranusjr/pythonup/pythonup
This installs everything you need to install Python runtimes, and provides a
PythonUp installs Pythons to
$HOME/Library/PythonUp. You should configure
your shell to add the following paths to your
PATH environment variable:
There is no official distribution for Linux at the current time (although Linuxbrew may work). You can perform a manual installation with Git. This is the configuration I use:
mkdir -p ~/.local/libexec/pythonup-posix cd ~/.local/libexec/pythonup-posix git clone https://github.com/uranusjr/pythonup-posix.git repo python3.6 -m venv --prompt=pythonup-posix venv ./venv/bin/python -m pip install --upgrade setuptools pip ./venv/bin/python -m pip install click dataclasses packaging ln -s $PWD/repo/pythonup ./venv/lib/python3.6/site-packages
Then you can create a script to run PythonUp like this:
#!/bin/sh exec $HOME/.local/libexec/pythonup-posix/venv/bin/python -m pythonup $*
Aside from usual Python dependencies, PythonUp also requires
- python-build from pyenv. You don’t need to install pyenv, only the
python-buildcommand. Clone the repository, and
ln -sthe command (in
pyenv/plugins/python-build/bin) into your
- Build dependencies for Python. pyenv maintains lists for common package managers: https://github.com/pyenv/pyenv/wiki#suggested-build-environment
Install Python 3.6:
$ pythonup install 3.6
Install Pipenv to Python 3.6:
$ pip3.6 install pipenv
And use it immediately (DOES NOT WORK YET, see TODO below):
$ pipenv --version pipenv, version 9.0.1
Install Python 2.7:
$ pythonup install 3.5-32
Switch to a specific version:
$ pythonup use 3.5 $ python3 --version Python 3.5.4
Switch back to 3.6:
$ pythonup use 3.6 $ python3 --version Python 3.6.4 $ python3.5 --version Python 3.5.4
$ pythonup uninstall 3.5
--help to find more:
$ pythonup --help $ pythonup install --help
PythonUp uses pyenv’s
python-build command to build the best match, and
install it into
$HOME/Library/PythonUp/versions/X.Y. Unlike pyenv, PythonUp
only lets you specify X.Y, not the micro part, so you can upgrade within a
minor version without breaking all your existing virtual environments.
Similar to pyenv (and PythonUp on Windows),
commands should be shimmed to allow auto-publishing hooks after you install a
package. Unlike the Windows implementation, some simple shell scripts will
suffice, fortunately. The script will be generated dynamically, when the user
use versions, to point to the correct version.
There are several disadvantages depending on Homebrew’s pyenv:
- pyenv does not release a new version to add a new Python definition.
- Homebrew does not always update the pyenv formula when pyenv releases.
Python 3.6.4, for example, was released on 2017-12-19. The python-build definition landed a few hours later, but is still not available as a versioned release (as of 2018-01-05). Judging from recent release patterns, availability of new Python versions can be delayed to up to one month after their official distribution.
I’m personally working around this by using the
HEAD version of pyenv (
brew install --HEAD pyenv), but this is not a good long-term solution. It
would be better to vendor python-build (maybe as a Git subtree), and update
when user queries Python versions (e.g. with
Another benefit of vendoring is that we don’t need the
to be globally available.
Obvious question: Why not just use pyenv? Because you always want to use the latest micro of a Python version, but pyenv doesn’t let you do that easily without breaking all your virtual environments and globally installed tools. Also the shims are a terrible idea.
I always say this, but all my projects are under-tested. Hashtag help-wanted.
It might be a good idea to unify the documentation? It makes sense from a user’s perspective because the interfaces are almost identical. The implementation and all underlying parts are different though. This would require some very careful planning.