Synopsis

Use pyenv to quickly install and switch between different Python releases while using pipenv to virtually isolate project files and libraries.

For example, create a virtual python environment using Python release 3.11.1 with pipenv command pipenv --python 3.11.1. If Python 3.11.1 is not installed on the local system pipenv will leverage pyenv to install and make it ready for use.

The be clear, pyenv and pipenv are completely separate tools from one another and operate with benefit independently. However, when they both exist together, the workflow of setting up a virtual python environment, based on various version requirements, is optimized.

For further details about the two tools,

Install steps

The following are the steps I took for installation on macOS. At the time of drafting this document, the release of macOS is 13.1 (Ventura). The hardware is Apple M1 Max.

pipenv

Using the host’s default python installation, install pipenv using pip.

pip install --user pipenv

Add pipenv to $PATH in the .zshrc file.

cd ~
vi .zshrc
export PATH=$PATH:/Users/user/Library/Python/3.9/bin
 (save and exit)

Check the installation using pipenv --help

user@host ~ % pipenv --help
Usage: pipenv [OPTIONS] COMMAND [ARGS]...

Options:
  --where                         Output project home information.
  --venv                          Output virtualenv information.
  --py                            Output Python interpreter information.
  --envs                          Output Environment Variable options.
  --rm                            Remove the virtualenv.
  --bare                          Minimal output.
  --man                           Display manpage.
  --support                       Output diagnostic information for use in
                                  GitHub issues.
  --site-packages / --no-site-packages
                                  Enable site-packages for the virtualenv.
                                  [env var: PIPENV_SITE_PACKAGES]
  --python TEXT                   Specify which version of Python virtualenv
                                  should use.
  --three                         Use Python 3 when creating virtualenv.
                                  Deprecated
  --clear                         Clears caches (pipenv, pip).  [env var:
                                  PIPENV_CLEAR]
  -q, --quiet                     Quiet mode.
  -v, --verbose                   Verbose mode.
  --pypi-mirror TEXT              Specify a PyPI mirror.
  --version                       Show the version and exit.
  -h, --help                      Show this message and exit.


Usage Examples:
   Create a new project using Python 3.7, specifically:
   $ pipenv --python 3.7

   Remove project virtualenv (inferred from current directory):
   $ pipenv --rm

   Install all dependencies for a project (including dev):
   $ pipenv install --dev

   Create a lockfile containing pre-releases:
   $ pipenv lock --pre

   Show a graph of your installed dependencies:
   $ pipenv graph

   Check your installed dependencies for security vulnerabilities:
   $ pipenv check

   Install a local setup.py into your virtual environment/Pipfile:
   $ pipenv install -e .

   Use a lower-level pip command:
   $ pipenv run pip freeze

Commands:
  check         Checks for PyUp Safety security vulnerabilities and against
                PEP 508 markers provided in Pipfile.
  clean         Uninstalls all packages not specified in Pipfile.lock.
  graph         Displays currently-installed dependency graph information.
  install       Installs provided packages and adds them to Pipfile, or (if no
                packages are given), installs all packages from Pipfile.
  lock          Generates Pipfile.lock.
  open          View a given module in your editor.
  requirements  Generate a requirements.txt from Pipfile.lock.
  run           Spawns a command installed into the virtualenv.
  scripts       Lists scripts in current environment config.
  shell         Spawns a shell within the virtualenv.
  sync          Installs all packages specified in Pipfile.lock.
  uninstall     Uninstalls a provided package and removes it from Pipfile.
  update        Runs lock, then sync.
  verify        Verify the hash in Pipfile.lock is up-to-date.
user@host ~ % 

pyenv

I used the “Basic GitHub Checkout” installation method. I thought this was an efficient “installation” method.

Open a terminal

cd ~
git clone https://github.com/pyenv/pyenv.git .pyenv

The following was used for the zsh default shell on macOS 13.1

echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.zshrc
echo 'command -v pyenv >/dev/null || export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.zshrc
echo 'eval "$(pyenv init -)"' >> ~/.zshrc

Close and reopen a new terminal shell.

Check the installation using pyenv --help

user@host ~ % pyenv --help  
Usage: pyenv <command> [<args>]

Some useful pyenv commands are:
   --version   Display the version of pyenv
   commands    List all available pyenv commands
   exec        Run an executable with the selected Python version
   global      Set or show the global Python version(s)
   help        Display help for a command
   hooks       List hook scripts for a given pyenv command
   init        Configure the shell environment for pyenv
   install     Install a Python version using python-build
   latest      Print the latest installed or known version with the given prefix
   local       Set or show the local application-specific Python version(s)
   prefix      Display prefixes for Python versions
   rehash      Rehash pyenv shims (run this after installing executables)
   root        Display the root directory where versions and shims are kept
   shell       Set or show the shell-specific Python version
   shims       List existing pyenv shims
   uninstall   Uninstall Python versions
   version     Show the current Python version(s) and its origin
   version-file   Detect the file that sets the current pyenv version
   version-name   Show the current Python version
   version-origin   Explain how the current Python version is set
   versions    List all Python versions available to pyenv
   whence      List all Python versions that contain the given executable
   which       Display the full path to an executable

See `pyenv help <command>' for information on a specific command.
For full documentation, see: https://github.com/pyenv/pyenv#readme
user@host ~ % 

Example

The following command creates a virtual python environment and installs the requested Python release.

mkdir project1 && cd project1
jneuffer@Humble project1 % pipenv --python 3.7.16
Warning: Python 3.7.16 was not found on your system...
Would you like us to install CPython 3.7.16 with Pyenv? [Y/n]: y
Installing CPython 3.7.16 with /Users/jneuffer/.pyenv/bin/pyenv (this may take a few minutes)...
✔ Success!
⠹ Installing python...patching file 'test/v3ext.c'
patching file 'Doc/library/ctypes.rst'
patching file 'Lib/test/test_unicode.py'
patching file 'Modules/_ctypes/_ctypes.c'
patching file 'Modules/_ctypes/callproc.c'
patching file 'Modules/_ctypes/ctypes.h'
patching file setup.py
patching file 'Misc/NEWS.d/next/Core and Builtins/2020-06-30-04-44-29.bpo-41100.PJwA6F.rst'
patching file 'Modules/_decimal/libmpdec/mpdecimal.h'
patching file setup.py
python-build: use zlib from xcode sdk

Creating a virtualenv for this project...
Pipfile: /Users/jneuffer/project1/Pipfile
Using /Users/jneuffer/.pyenv/versions/3.7.16/bin/python3.7m (3.7.16) to create virtualenv...
⠸ Creating virtual environment...created virtual environment CPython3.7.16.final.0-64 in 307ms
  creator CPython3Posix(dest=/Users/jneuffer/.local/share/virtualenvs/project1-TKHsXDeN, clear=False, no_vcs_ignore=False, global=False)
  seeder FromAppData(download=False, pip=bundle, setuptools=bundle, wheel=bundle, via=copy, app_data_dir=/Users/jneuffer/Library/Application Support/virtualenv)
    added seed packages: pip==22.3.1, setuptools==65.6.3, wheel==0.38.4
  activators BashActivator,CShellActivator,FishActivator,NushellActivator,PowerShellActivator,PythonActivator

✔ Successfully created virtual environment!
Virtualenv location: /Users/jneuffer/.local/share/virtualenvs/project1-TKHsXDeN
Creating a Pipfile for this project...
screenshot of the above request

Using pipenv shell we can drop into the new virtual project.

jneuffer@Humble project1 % pwd
/Users/jneuffer/project1

jneuffer@Humble project1 % pipenv shell
Launching subshell in virtual environment...
Restored session: Sat Dec 24 12:36:09 EST 2022
 . /Users/jneuffer/.local/share/virtualenvs/project1-TKHsXDeN/bin/activate
jneuffer@LivingRoom1 project1 %  . /Users/jneuffer/.local/share/virtualenvs/project1-TKHsXDeN/bin/activate

(project1) jneuffer@Humble project1 % python --version
Python 3.7.16

(project1) jneuffer@Humble project1 % pip list
Package    Version
---------- -------
pip        22.3.1
setuptools 65.6.3
wheel      0.38.4
(project1) jneuffer@Humble project1 % 

Let’s install pandas inside the virtual python environment.

The following screenshot shows the output from issuing the command, (project1) jneuffer@Humble project1 % pip install pandas

We’ve installed pandas inside the virtual python environment. Now we’ll do a pip list to see what that looks like.

(project1) jneuffer@Humble project1 % pip list
Package         Version
--------------- -------
numpy           1.21.6
pandas          1.3.5
pip             22.3.1
python-dateutil 2.8.2
pytz            2022.7
setuptools      65.6.3
six             1.16.0
wheel           0.38.4
(project1) jneuffer@Humble project1 %

Now let’s leave the virtual python environment.

(project1) jneuffer@Humble project1 % exit

Saving session...
...saving history...truncating history files...
...completed.
jneuffer@Humble project1 % 

Conclusion

These two tools can streamline the need to use specific release versions of not only Python, but also specific releases of modules.

There are other approaches to isolating Python and modules, such as VMs (Vagrant) and containers. These approaches are just as interesting as the method described above. Everything has a set of pro/con and requirements; therefore, having more than one solution to solve a problem is a good thing.

Last modified: 12/24/2022

Comments

Write a Reply or Comment