Definitive guide to python on Mac OSX
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
poetry for python version management and python package/venv management, respectively.
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?
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 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:
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 .
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)"
Now that Homebrew is installed, you can install pyenv and the required packages to install python.
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
(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
blackthat 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.
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
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
Congratulations, you have python! Done, right?? Nope.
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:
requirements.txt, and more.
- Lives outside python, so you don’t need to install it with
pipor worry about package conflicts.
- Separates runtime dependencies like
requestsfrom development dependencies like
- It uses the simple and easy-to-understand
pypackage.tomlfile from pep-518 to contain everything about the project.
- CLI interface similar to well-known package managers like
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
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
~/.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
gpip3 to override this protection and force a package to install globally.
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
Decide on a python version for this project:
pyenv local 3.7.3
Then add dependencies to the project, such as the
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
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
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.