Python setup
I’m using pyenv
to manage the overall “system” Python, and venv
to manage
per-project virtual environments.
pyenv
allows you to install multiple versions of Python on your system
and switch between them. You can manage a global Python, or have more
specific rules like per-directory or per shell. We’ll just use
it for our system Python since venv
will handle the virtual environments
for each project.
One nice thing about pyenv
is that it is independent of any Python
install on your system, since it is just a collection of shell scripts.
Set up pyenv
brew install pyenv
After this, the pyenv
command will work, but we don’t have the shims
set up yet.
Following the pyenv
instructions, we need
to make sure the following is at the end of the shell configuration file:
if command -v pyenv 1>/dev/null 2>&1; then
eval "$(pyenv init -)"
fi
The file will depend on which shell you are using:
- bash:
~/.bash_profile
or~/.bashrc
- regular zsh:
~/.zshrc
- Oh My Zsh:
~/.oh-my-zsh/custom/for_pyenv.zsh
Make sure to restart the shell to activate the changes.
You can check that the shims are set up properly by typing
which python
, which should give you something like
/Users/ajfriend/.pyenv/shims/python
Warning
Note that for some reason, the shim redirection doesn’t work
if you only have system Python. So you may not see
the expected which python
output until you’ve installed
at least one python version with pyenv
.
Preparing for installing new Pythons
We then need to install any Python build dependencies before trying to add a new version of Python. Use the following:
brew install openssl readline sqlite3 xz zlib
New versions of Python can then be installed with a command like
pyenv install 2.7.8
It is also good practice to follow that command with a
pip install --upgrade pip setuptools wheel
after you’ve selected the new python to be global
.
Debugging
Note
If you have any issues with the command above, you might make sure that you have dependencies installed:
xcode-select --install
brew install autoconf bzip2 libffi ncurses openssl pkg-config readline sqlite3 xz zlib
This page is pretty good: https://github.com/pyenv/pyenv/wiki/Common-build-problems
I was seeing this issue:
> virtualenv
/Users/ajfriend/.pyenv/shims/virtualenv: line 21: /usr/local/Cellar/pyenv/1.2.20/libexec/pyenv: No such file or directory
but this was fixed by running pyenv rehash
.
Issues with zlib
Note that you may see the warning below from brew
:
zlib is keg-only, which means it was not symlinked into /usr/local,
because macOS already provides this software and installing another version in
parallel can cause all kinds of trouble.
For compilers to find zlib you may need to set:
export LDFLAGS="-L/usr/local/opt/zlib/lib"
export CPPFLAGS="-I/usr/local/opt/zlib/include"
For pkg-config to find zlib you may need to set:
export PKG_CONFIG_PATH="/usr/local/opt/zlib/lib/pkgconfig"
In that case, something like the flow below should work (based on this Stack Overflow answer):
brew install zlib
export LDFLAGS="-L/usr/local/opt/zlib/lib"
export CPPFLAGS="-I/usr/local/opt/zlib/include"
pyenv install 3.7.2
WARNING: The Python bz2 extension was not compiled. Missing the bzip2 lib?
In this case, brew install bzip2
. You may also need to set compiler
flags. If you need to set flags for both zlib
and bz2
, you can
concatenate the flags like
export LDFLAGS="-L/usr/local/opt/zlib/lib -L/usr/local/opt/bzip2/lib"
export CPPFLAGS="-I/usr/local/opt/zlib/include -I/usr/local/opt/bzip2/include"
pyenv install 3.9.0
numpy
issues with Python 3.9
I was seeing an error like RuntimeError: Polyfit sanity test emitted a warning...
This was fixed with (and potentially in addition to the fixes above):
export OPENBLAS="$(brew --prefix openblas)"
pyenv install 3.9.0
A pip cache remove numpy
may or may not have helped, too.
pyenv
commands
-
pyenv versions
shows all installed Python versions;
*
denotes the one currently active❯ pyenv versions * system (set by /Users/ajfriend/.pyenv/version) 3.7.9 3.8.5 3.9.0
-
pyenv install --list
list all Python versions available for installation
-
pyenv install 2.6.8
installs a version of python
-
pyenv uninstall <version>
-
pyenv version
shows currently active Python
❯ pyenv version 3.9.0 (set by /Users/ajfriend/.pyenv/version)
-
pyenv global 2.7.6
set the “global/system” Python
-
pyenv which <command>
Displays the full path to the executable that
pyenv
will invoke when you run the given command❯ pyenv which pip /Users/ajfriend/.pyenv/versions/3.9.0/bin/pip
Using venv
for virtual environments
pyenv
can help you manage virtual environments, but I prefer to do things
manually with venv
.
I’ll generally make a virtual environment for each separate project within that project’s folder. To do this, first select the version of Python you’d like to use for the virtual environment:
pyenv versions
pyenv global 3.7.9
Then, within the project directory, run
python -m venv env
which will create a virtual environment in the env
directory.
Now you can activate/deactivate your environment, or just run things directly with commands like:
env/bin/python
env/bin/pip
env/bin/jupyter lab
Disabling pyenv
pyenv global system
will set things back to the “system” Python,
but pyenv
is still handling the logic that determines which Python to use.
To stop pyenv
from using its shims to determine which Python to use,
just remove the pyenv init
code that we added above to our shell config file.
For more details, see https://github.com/pyenv/pyenv#uninstalling-pyenv.
pyenv
references
- Stop Homebrew Version-Jacking Your Python All The Time
- https://opensource.com/article/19/5/python-3-default-mac
- https://realpython.com/intro-to-pyenv/
- https://github.com/pyenv/pyenv