Definitive guide to python on Mac OSX

Brian Torres-Gil
6 min readMay 13, 2017

--

You should setup python on your Mac this way. I’m tired of having to look this up, or worse, describe it ineffectively to coworkers. So here it is, all in one place.

UPDATED for python 2 EOL: Many things have changed in python-land, including the retirement of python 2.7, so I updated this guide to reflect current best practices. Highlights: removed requirement to install Xcode, no longer uses the obsolete virtualenv and virtualenvwrapper, added pyenv and poetry for python version management and python package/venv management, respectively.

Photo by Chris Ried on Unsplash

Why this way?

You have python on your Mac, can’t you use the built-in python? Isn’t any other method just for experts?

NO!

Here are the problems with using the built-in python:

  • Installed PyPi packages pollute your system python, potentially causing system problems
  • OpenSSL used by the system python is old and vulnerable. Old as in, doesn’t understand websites that require TLS 1.1 or later
  • You’re stuck with whatever python 2.7 version comes pre-installed, and no python 3.x

Install Xcode (optional)

Xcode is not required to install Homebrew and Python, but it is required for some Homebrew packages. If you can spare the gigabytes, download it from the App Store. If not, you should be able to complete this guide without it on MacOS Mojave. No guarantee for future versions of MacOS.

Install Xcode from the App Store

Install Xcode Command Line Tools (required)

While Xcode is not required, the Xcode Command Line Tools are.

Open a terminal and type the following command to install Xcode Command Line Tools which are required for Homebrew:

xcode-select --install

If you’re using MacOS Mojave, you’ll need to install the MacOS system headers. This is not required for Catalina.

sudo installer -pkg /Library/Developer/CommandLineTools/Packages/macOS_SDK_headers_for_macOS_10.14.pkg -target /

You’ll be prompted for your OSX user password to install this required SDK package.

If you chose not to install Xcode, you’ll need to add the SDKROOT environment variable to your shell:

echo "export SDKROOT=/Library/Developer/CommandLineTools/SDKs/MacOSX10.14.sdk" >> ~/.bash_profile

If using zsh, change the end of that last command from ~/.bash_profile to ~/.zshrc .

Install Homebrew

Homebrew is a package manager for OSX. We’ll use it to install the dependencies to compile and install python. (Note: previous versions of this guide used Homebrew to install python, but this is not required. We’ll use pyenv to install python shortly.)

Go here: https://brew.sh/

Follow the directions to install Homebrew, which at the time of this writing is to paste this line into a terminal:

/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)"

Install pyenv

Now that Homebrew is installed, you can install pyenv and the required packages to install python.

Install pyenv:

brew install pyenv

Install python required packages:

brew install openssl readline sqlite3 xz zlib

Add pyenv to your shell:

echo -e 'if command -v pyenv 1>/dev/null 2>&1; then\n  eval "$(pyenv init -)"\nfi' >> ~/.bash_profile

If using zsh, change the end of that last command from ~/.bash_profile to ~/.zshrc .

(Optional) You can also brew install pyenv-virtualenv to add virtualenv support to pyenv, but it’s not required since most of the virtualenv work you’ll do with poetry after we install it later. Some people like the pyenv-virtualenv support anyway.

Install Python with Homebrew

This step is optional since we’ll never use this python in a project, but it’s recommended for two reasons:

  • Reason 1: This Homebrew-installed python becomes a safety net in case we forget to switch to a pyenv-installed python, we won’t accidentally pollute the system python.
  • Reason 2: It becomes a place to install global packages with pipx. This allows you to switch between python versions at-will using pyenv while maintaining a consistent set of global utilities like flake8 and black that are always available and don’t pollute the global python.

Install latest python 3.x and pipx
(Optional, for global packages)

# Install python 3.x
brew install python
# Install pipx to manage global packages
python3 -m pip install --user pipx
python3 -m userpath append ~/.local/bin
# Install global packages
python3 -m pipx install flake8
python3 -m pipx install black

Install latest python 2.7
(Really optional, only to protect system python from mistakes)

brew install python@2

If you chose to install python 2.7, you will never use it (unless you have some legacy code you need to run). Python 2.7 end of life is at the end of 2019. See the Python 2.7 end-of-life countdown. It’s only acting as a safety net to protect the system python in case you make a mistake.

Install python!

Finally! Time to install python…

Let’s start with a fresh shell. Close your terminal and open it again to ensure pyenv has been loaded.

You can see a list of available python versions with pyenv:

$ pyenv install --list
...
3.6.1
3.6.2
3.6.3
3.6.4
3.6.5
3.6.6
3.6.7
3.6.8
3.7.0
3.7-dev
3.7.1
3.7.2
3.7.3
3.8-dev
3.9-dev
<snip>
anaconda3-5.0.0
anaconda3-5.0.1
anaconda3-5.1.0
anaconda3-5.2.0
anaconda3-5.3.0
anaconda3-5.3.1
anaconda3-2018.12
anaconda3-2019.03
...

Pick a version and install it:

pyenv install 3.7.3

Then set it as the global python version:

pyenv global 3.7.3

This should take effect right away. Verify that you’re on the right python version:

$ python -V
Python 3.7.3

Congratulations, you have python! Done, right?? Nope.

Install Poetry

Poetry is a fantastic python package manager that simplifies dependency management, virtual environment management, and building and publishing of python code.

Why you should use poetry:

  • Obsoletes virtualenv, virtualenvwrapper, pipenv, setup.py, requirements.txt, and more.
  • Lives outside python, so you don’t need to install it with pip or worry about package conflicts.
  • Separates runtime dependencies like requests from development dependencies like pytest.
  • It uses the simple and easy-to-understand pypackage.toml file from pep-518 to contain everything about the project.
  • CLI interface similar to well-known package managers like npm and yarn.

Install poetry following the installation guide. At the time of this writing, simply run this command:

curl -sSL https://raw.githubusercontent.com/sdispater/poetry/master/get-poetry.py | python

Poetry creates all your virtual environments automatically on-demand in a single directory by default. If you prefer your virtual environments to live in the same directory with the code (like a .venv directory in your project), you can run this command:

poetry config virtualenvs.in-project true

Learn more about poetry

Prevent accidents

Now we’ll add a few important pieces to the terminal environment to ensure everything works together and keep from breaking our carefully constructed python development environment.

Open the file ~/.bash_profile (or ~/.zshrc for zsh). Create that file if it doesn’t exist and make sure it has the following lines:

Save the file, then close and re-open your terminal window to activate the changes.

You have now activated pipx, pyenv, poetry, and locked down pip to only work inside a virtual environment so you can’t accidentally install python packages to the global python environment. Don’t worry, if you still want to install a python package globally (you don’t!) you can use gpip or gpip3 to override this protection and force a package to install globally.

Go forth!

You’re now ready to work with python!

You no longer need to create virtual environments or write confusing boilerplate.

Simply create a new python project:

poetry new myproject
cd myproject

Decide on a python version for this project:

pyenv local 3.7.3

Then add dependencies to the project, such as the requests package:

poetry add requests

And your development dependencies:

poetry add --dev pytest

A virtual environment is automatically created with the python version you chose and the added python packages.

You never need to enter this virtual environment. No more .venv/bin/activate or deactivate. Although you can if you want to. You can also create your own unmanaged virtual environments by using the latest venv features built into python 3 to create your virtual environments. Don’t use virtualenv.

To run your project in the virtual environment, do something like this:

poetry run python myscript.py

Or create a scripts section in pyproject.py to make the entrypoint available outside the virtual environment.

See the documentation for the run command in poetry for various ways to run your python projects from the CLI.

Enjoy!

--

--