Skip to content

Virtual Environments

A virtual environment solves the “dependency hell” problem. When multiple Python projects share the global system Python, upgrading a library for one project can break another. A virtual environment creates an isolated sandbox.

When an environment is created, it builds an isolated directory tree.

  • Binaries: It contains its own python and pip executable wrappers.
  • Libraries: It creates a dedicated site-packages directory. When pip install is run while the environment is active, the package goes only into this specific folder, never the system folder.
  • Installation: refer → https://github.com/pyenv/pyenv?tab=readme-ov-file#1-automatic-installer-recommended

    Terminal window
    > curl -fsSL https://pyenv.run | bash
    > echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.bashrc
    echo '[[ -d $PYENV_ROOT/bin ]] && export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.bashrc
    echo 'eval "$(pyenv init - bash)"' >> ~/.bashrc
    > echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.profile
    echo '[[ -d $PYENV_ROOT/bin ]] && export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.profile
    echo 'eval "$(pyenv init - bash)"' >> ~/.profile
    > echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.bash_profile
    echo '[[ -d $PYENV_ROOT/bin ]] && export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.bash_profile
    echo 'eval "$(pyenv init - bash)"' >> ~/.bash_profile
  • Discover Versions: $ pyenv install -l (Lists all Python versions available to download).

  • Install Version: $ pyenv install <version> (Downloads and compiles that version on your machine).

  • Create Isolation: $ pyenv virtualenv <version> <venv_name> (Creates the sandbox).

  • Manual Activation: $ pyenv activate <venv_name> (Attaches the current terminal session to the sandbox).

  • Manual Deactivation: $ pyenv deactivate (Detaches the terminal from the sandbox).

  • Automated Activation (Workspace Shifting): $ pyenv local <venv_name> (Writes a .python-version file in the directory. Pyenv will automatically activate this environment whenever you cd into this directory).


4. Practical Implementation: Creating and Shifting Workspaces

Section titled “4. Practical Implementation: Creating and Shifting Workspaces”

$ pyenv install 3.10.1 $ pyenv install 3.11.1

Step 2: Create two isolated virtual environments

Section titled “Step 2: Create two isolated virtual environments”

$ pyenv virtualenv 3.10.1 project_one_env $ pyenv virtualenv 3.11.1 project_two_env

We navigate to the Desktop, create the first folder, and bind the 3.10.1 environment to it.

Terminal window
$ cd ~/Desktop
$ mkdir project_one
$ cd project_one
# Bind the environment
$ pyenv local project_one_env
# The prompt changes silently in the background. Install a package here.
$ pip install requests
$ pip freeze
certifi==2024.2.2
charset-normalizer==3.3.2
idna==3.6
requests==2.31.0
urllib3==2.2.1

We move out of project_one (which automatically drops the 3.10.1 environment), create the second folder, and bind the 3.11.1 environment.

Terminal window
$ cd ~/Desktop
$ mkdir project_two
$ cd project_two
# Bind the second environment
$ pyenv local project_two_env
# Install a completely different package here.
$ pip install beautifulsoup4
$ pip freeze
beautifulsoup4==4.12.3
soupsieve==2.5

Step 5: Verifying the Isolation (Shifting between them)

Section titled “Step 5: Verifying the Isolation (Shifting between them)”

By simply navigating between these two directories on your Desktop, pyenv dynamically updates your $PATH.

Terminal window
$ cd ~/Desktop/project_one
$ which python
/home/pavan_bandaru/.pyenv/envs/project_one_env/bin/python
$ python --version
Python 3.10.1
$ cd ~/Desktop/project_two
$ which python
/home/pavan_bandaru/.pyenv/envs/project_two_env/bin/python
$ python --version
Python 3.11.1

The Logical Conclusion:

In this setup, project_one has zero access to beautifulsoup4, and project_two has zero access to requests. If you run python from ~/Desktop itself, it will default to your system’s Python 3.9.25. They exist as parallel, uncontaminated systems.


1. pyenv activate <venv_name> (The Manual Override)

Section titled “1. pyenv activate <venv_name> (The Manual Override)”
  • The Logic: Instead of relying on directory-based automation (where cd changes your environment), this command forces your current terminal session into the specified environment, no matter what folder you are currently inside.
  • In Your Context: If you are sitting in ~/Downloads (which normally uses your system Python 3.9.25), running pyenv activate project_one_env instantly switches your interpreter to 3.10.1 and grants you access to the requests library.

2. pyenv deactivate (The Manual Detachment)

Section titled “2. pyenv deactivate (The Manual Detachment)”
  • The Logic: This reverses the activate command. It unhooks your terminal session from the manually forced environment and returns control to the default state (either the global system Python or whatever pyenv local dictates for your current directory).
  • In Your Context: If you run this while inside project_one_env, your terminal drops the 3.10.1 isolation and falls back to whatever Python version is designated for the folder you are currently standing in.

3. pyenv uninstall <venv_name> (The Permanent Destruction)

Section titled “3. pyenv uninstall <venv_name> (The Permanent Destruction)”
  • The Logic: This performs a physical deletion. It wipes the isolated bin (executables) and site-packages (installed libraries) directories from your ~/.pyenv/versions/ folder.
  • In Your Context: Running pyenv uninstall project_two_env permanently deletes that 3.11.1 sandbox. The project_two folder on your Desktop will still exist, but the .python-version file inside it will now point to a deleted environment, causing an error if you try to run Python there until you assign a new one.