Installing Python and Managing Versions
Official Installers: python.org, Windows Store, and Homebrew
The official Python installers from python.org represent the most direct and universally supported method for installation. They are maintained by the Python Software Foundation (PSF) and provide a consistent, predictable experience across platforms. For Windows users, the Microsoft Store offers an alternative, while macOS users often turn to the Homebrew package manager. Each method has distinct advantages and philosophical approaches to system integration.
The python.org Installers
Downloading the installer from python.org is the canonical method. It provides the greatest control over the installation process. During installation on Windows, you are presented with a crucial option: “Add Python X.X to PATH”. This checkbox is deselected by default for historical reasons, primarily to avoid conflicting with any pre-existing Python versions that a user might have manually installed. Not selecting this is the single most common pitfall for beginners, as it renders the python command unusable from the Command Prompt or PowerShell. The installer also includes the pip package manager and the IDLE development environment by default.
For a standard user installation on Windows, you would download the “Windows installer (64-bit)” executable. The installation can be verified by opening a new Command Prompt (a restart of the shell is necessary to recognize the updated PATH) and running:
python --version
pip --version
If these commands are not recognized, the PATH variable was not set correctly. This can be remedied manually by adding the installation directory (e.g., C:\Users\YourUser\AppData\Local\Programs\Python\Python312) and its Scripts subfolder to the system’s PATH environment variable.
On macOS, the python.org installer is a standard .pkg file that places Python in the /Library/Frameworks/Python.framework/Versions/ directory. It will also create a symlink in /usr/local/bin/ (or prompt you to update your shell profile) to make the python3 and pip3 commands available. This method installs a self-contained Python distribution that does not interfere with the system Python in /usr/bin/.
The Microsoft Store Package
On Windows 10 and 11, Python is available through the Microsoft Store. This method is often simpler for new users as it handles PATH management and updates automatically. The Store version runs in a lightweight “Windows Application” environment, which provides better isolation from the core system files. However, this isolation can be a double-edged sword. Some advanced tools or libraries that rely on specific file system permissions or expect a traditional installation layout might encounter edge cases or fail to work correctly. Furthermore, because the installation is managed by the Windows Store, its location is not as straightforward to reference in development tools or scripts.
To install via the Store, simply search for “Python” and select the latest version from the Python Software Foundation. Verification is the same as for the python.org installer. The key advantage here is the elimination of the “PATH” problem; it is configured for you.
Homebrew on macOS
For macOS users who prefer a command-line workflow and use Homebrew as their primary package manager, installing Python is a natural choice. Homebrew installs packages into its own prefix (/usr/local on Intel Macs, /opt/homebrew on Apple Silicon Macs), keeping them entirely separate from the system software. This is a significant best practice for development on macOS, as it prevents you from accidentally modifying the system’s own Python, which macOS relies on for internal tasks.
Installation is performed with a single command:
brew install python
This will install the latest Python 3 version and the associated pip. Homebrew automatically links the formulae into your PATH, making python3 and pip3 available immediately. A critical detail is that Homebrew formulae are named python but install the command as python3 to avoid shadowing the system’s python command (which points to Python 2.7 on older macOS versions). This explicit naming prevents confusion and ensures scripts are written portably. To manage multiple versions, Homebrew is often paired with the pyenv tool for more granular control, as Brew itself is better suited for maintaining a single, active version of a formula.
pyenv: Installing and Switching Python Versions
To effectively manage multiple Python versions on a single system, pyenv is the indispensable tool of choice for developers. It operates on a simple yet powerful principle: it intercepts Python commands using shim executables and redirects them to the specific Python version configured for your current directory or shell session. This is achieved by prepending a special directory (~/.pyenv/shims) to your $PATH. When you run python or pip, your shell finds the pyenv shim first. This shim then consults pyenv to determine which Python version to use based on your current context (global, local, or shell setting) and passes the command along to the correct, actual Python installation. This elegant approach completely avoids the need to manually modify $PATH for different projects and eliminates the chaos of system-wide Python version changes.
Installing pyenv on Unix-like Systems
The recommended installation method uses the pyenv-installer script. Before running it, you must install the required OS-level dependencies for building Python from source. These include development tools, libraries like zlib and sqlite, and SSL headers. On Ubuntu/Debian, this is typically: sudo apt-get install -y make build-essential libssl-dev zlib1g-dev libbz2-dev libreadline-dev libsqlite3-dev wget curl llvm libncurses5-dev libncursesw5-dev xz-utils tk-dev libffi-dev liblzma-dev python3-openssl git. After installing dependencies, you can fetch and execute the installer script: curl https://pyenv.run | bash. The output will instruct you to add three lines to your shell startup file (e.g., ~/.bashrc or ~/.zshrc) to enable pyenv. The crucial line is adding $HOME/.pyenv/bin to your PATH and initializing pyenv.
# Add the following to your ~/.bashrc or ~/.zshrc
export PATH="$HOME/.pyenv/bin:$PATH"
eval "$(pyenv init --path)"
eval "$(pyenv init -)"
You must start a new shell session or source your profile (source ~/.bashrc) for these changes to take effect. Verify the installation with pyenv --version.
Listing and Installing Available Python Versions
Once installed, you can view all available Python versions, including stable releases, development branches, and alternative implementations like pypy and anaconda3. The command pyenv install --list (or pyenv install -l) will output a very long list. To install a specific version, use pyenv install <version>. This command downloads the source code and compiles it, which can take several minutes. For example, to install the latest Python 3.11 patch version and the end-of-life Python 3.6 for legacy project support, you would run:
pyenv install 3.11.4
pyenv install 3.6.15
After installation, these versions are stored in ~/.pyenv/versions/. You can see all versions known to pyenv (both installed and not) with pyenv versions. The asterisk (*) indicates the currently active version.
Setting Global, Local, and Shell Python Versions
pyenv provides three scopes for version management. The global version is the default fallback used if no other version is specified. Set it with pyenv global <version>. It’s wise to set this to a stable, recent version you use for general scripting. The local version is the most powerful feature. It sets the Python version for a specific project directory by creating a .python-version file. pyenv automatically detects this file when you are in that directory or its subdirectories. This allows every project to declare its own required version independently. Set it with pyenv local <version>. The shell version is a temporary setting that only affects your current shell session and overrides both global and local settings. It’s set with pyenv shell <version> and is stored in the $PYENV_VERSION environment variable.
# Set the default system-wide version
pyenv global 3.11.4
# Navigate to your project and set its specific version
cd ~/my_legacy_project
pyenv local 3.6.15
# Now, temporarily use a different version for a one-off task
pyenv shell 3.9.13
python --version # Will output 'Python 3.9.13'
exit # or close the terminal to end the shell session
Understanding the PYENV_VERSION Environment Variable
The PYENV_VERSION environment variable is the core mechanism behind scoped version selection. When you use pyenv shell, it sets this variable. The pyenv shims check this variable first to decide which Python to use. If it’s not set, they then look for a .python-version file in the current and parent directories (the “local” scope). If that file is not found, they finally fall back to the “global” version defined in ~/.pyenv/version. You can manually export this variable yourself for advanced scripting scenarios, e.g., export PYENV_VERSION=3.8.10.
Common Pitfalls and Best Practices
A common pitfall is forgetting to install the build dependencies, which causes the pyenv install command to fail with often cryptic compiler errors about missing headers. Always consult your OS documentation for the prerequisite packages. Another issue arises with pip and virtual environments. While pyenv manages the Python binary, you should always use a virtual environment (managed by venv, virtualenv, or pipenv) for project dependencies. The pyenv -managed Python is the base interpreter; the virtual environment creates an isolated copy of it for your project’s packages. Never install packages directly into a pyenv-managed Python version using pip install --user or sudo pip install, as this creates dependency conflicts between projects. The best practice workflow is: 1) pyenv local 3.11.4, 2) python -m venv .venv, 3) source .venv/bin/activate. This ensures your project uses both the correct Python version and an isolated package environment.
conda and Miniconda: Managing Environments and Packages
While pip and venv are the standard tools for Python package management, they are largely Python-specific. Conda, by contrast, is a cross-platform, language-agnostic package manager and environment manager developed by Anaconda, Inc. It was created to solve complex scientific computing needs, where dependencies often extend beyond Python to include compiled binaries libraries for C, C++, Fortran, and R. Miniconda is a minimal, bootstrap version of the larger Anaconda distribution; it includes only conda, Python, the packages they depend on, and a small number of other useful packages. This makes it the preferred choice for most developers who want the power of conda without the pre-installed bulk of hundreds of scientific packages.
The Architecture of Conda Environments
A conda environment is not merely a folder of symlinks like venv. It is a self-contained directory that contains a specific collection of conda packages. Crucially, conda manages more than just Python packages. Each environment can have its own independent set of any kind of package—a specific version of Python, a Python library, a C library, or a command-line tool. Conda achieves this by solving a massive SAT problem for every installation or update operation, finding a compatible set of all packages (their dependencies and conflicts) across all languages for the target platform. This holistic approach is why conda excels in complex, multi-language projects but can be slower than pip for pure-Python workflows.
Installing Miniconda
You should download the latest Miniconda installer for your operating system from the official repository. The installation process is straightforward but differs slightly between Windows, macOS, and Linux. For Linux/macOS, it involves running a bash script. Always prefer the 64-bit version.
# Example for Linux x86_64
wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh
bash Miniconda3-latest-Linux-x86_64.sh
# Follow the prompts. It is highly recommended to answer 'yes' to
# "Do you wish the installer to initialize Miniconda3 by running conda init?"
# This will configure your shell to use conda.
After installation, close and reopen your terminal. Your prompt should now be prefixed with (base), indicating you are in the default base environment.
Creating and Activating Environments
The conda create command is used to create a new environment. The -n flag specifies the environment name, and you can list packages to install immediately. A best practice is to always install python explicitly when creating an environment for a project to control the exact version used.
# Create an environment named 'my_project' with Python 3.11
conda create -n my_project python=3.11
# Create an environment with multiple specific packages at once
conda create -n data_sci python=3.10 numpy=1.23 pandas scikit-learn
# To activate the environment (the command is OS-specific)
conda activate my_project # Linux/macOS and Windows (Command Prompt/PowerShell)
# activate my_project # Windows (Command Prompt only - older syntax)
# Once activated, your prompt changes to (my_project)
# To deactivate the current environment and return to 'base'
conda deactivate
Installing Packages with Conda
Within an activated environment, you use conda install to add packages. Conda installs packages from “channels,” which are repositories of pre-built packages. The default channel is maintained by Anaconda, Inc. For a wider array of community-maintained packages, especially the latest versions of scientific libraries, the conda-forge channel is essential.
# Install a package from the default channel
conda install django
# Install a specific version of a package
conda install numpy=1.24
# Install a package from the conda-forge channel
conda install conda-forge::celery
# You can also add conda-forge to your channel priorities permanently.
# This is a common best practice to ensure package availability.
conda config --add channels conda-forge
conda config --set channel_priority strict # Tells conda to prefer packages from conda-forge when they exist
The environment.yml File: Reproducible Environments
For project reproducibility, conda uses an environment.yml file. This file declaratively specifies all dependencies, including Python version, conda channels, and both conda and pip packages. This is far more robust than a requirements.txt file for conda-based projects because it captures non-Python dependencies.
# environment.yml
name: my_web_app # Name of the environment (optional)
channels:
- conda-forge
- defaults
dependencies:
- python=3.11
- django=4.2
- gunicorn
- pip # You can mix conda and pip packages
- pip:
- django-debug-toolbar # If a package is only available on PyPI
To create an environment from this file:
conda env create -f environment.yml
To update an existing environment after changes to the file:
conda env update -f environment.yml --prune # The --prune flag removes any packages not in the file
Managing Environments and Channels
It’s crucial to know how to inspect and manage your environments and configuration.
# List all available environments (the active one is marked with *)
conda env list
# or
conda info --envs
# List all installed packages in the current environment
conda list
# Remove an entire environment
conda remove -n my_project --all
# Remove a single package from the current environment
conda remove numpy
# Search for a package to see available versions
conda search "django>=4.0"
# View your conda configuration, including channels
conda config --show
Common Pitfalls and Best Practices
- Mixing Conda and Pip: While possible, installing all possible packages with conda first is a best practice. Using
pipinside a conda environment can sometimes lead to dependency conflicts becausepipis unaware of conda’s non-Python packages. If you must usepip, do it as shown in theenvironment.ymlexample and avoid mixing them for the same package. - Channel Priority: The order of channels in your configuration matters. Using
conda config --set channel_priority strictis recommended to prevent unexpected package combinations from different channels. - The
baseEnvironment: Avoid installing project-specific packages into thebaseenvironment. Treat it as a system-level tool only for installing conda itself and perhaps global utilities. Isolate every project in its own environment to prevent conflicts. - Performance: Conda’s solver can be slow for large environments. The open-source alternative, Mamba, is a drop-in replacement for the conda client that uses a much faster solver (
libsolv). You can install it withconda install conda-forge::mambaand then use commands likemamba create -n my_env python=3.11 numpyfor significantly faster operations.
uv: The Blazing-Fast Python Package and Project Manager
uv is an exceptionally fast, all-in-one Python project and package manager written in Rust, designed as a drop-in replacement for the combined workflows of pip, pip-tools, virtualenv, venv, and pyenv. Its core philosophy is to leverage Rust’s performance and safety guarantees to eliminate the frustrating latency traditionally associated with Python tooling, making dependency resolution and environment creation near-instantaneous. It is not merely an incremental improvement but a paradigm shift, developed by Astral (the creators of Ruff) and rapidly becoming the standard for new Python projects.
Why Choose uv?
The primary reason to adopt uv is its staggering performance. Where pip can take tens of seconds or even minutes to resolve complex dependency graphs, uv often completes the task in less than a second. This speed stems from its use of a highly-optimized, Rust-based dependency resolver and its integration with the global PyPI package cache, which avoids redundant downloads. Beyond speed, uv consolidates multiple tools into a single, consistent interface (uv pip, uv venv, uv python), reducing cognitive overhead and the potential for errors caused by misconfigured toolchains. It also offers superior reproducibility by using the latest standards by default, such as pip-compile-style locked dependencies and the modern pyproject.toml.
Installation and Setup
uv can be installed via a single, standalone command that downloads a pre-built binary. This method works on most Unix-like systems (Linux, macOS) and Windows. It does not require a prior Python installation, making it ideal for bootstrapping new systems.
# On macOS, Linux, or Windows (WSL)
curl -LsSf https://astral.sh/uv/install.sh | sh
Once installed, add ~/.local/bin (or the specified directory) to your PATH. You can verify the installation by running uv --version. For Windows (Powershell), a separate installation script is available.
Creating and Activating Virtual Environments
A core feature of uv is its ability to create isolated virtual environments instantly. Unlike the standard venv module, uv’s environment creation is not bottlenecked by copying the base Python interpreter.
# Create a virtual environment named '.venv' in the current directory
uv venv
# Create a virtual environment with a specific name
uv venv my_project_env
# Create an environment using a specific Python version (if available via `uv python`)
uv venv --python 3.11 .venv
To activate the environment, use the standard shell commands. uv creates fully compatible environments.
# On macOS/Linux:
source .venv/bin/activate
# On Windows (Powershell):
.venv\Scripts\activate
Managing Dependencies and Installing Packages
The uv pip command provides a superset of pip’s functionality but with vastly improved performance. You can install packages directly, similar to pip install.
# Install a single package
uv pip install requests
# Install multiple packages and a package from a Git repository
uv pip install httpx "pydantic>2.0" git+https://github.com/username/some_package.git
# Install all dependencies from a requirements.txt or pyproject.toml
uv pip install -r requirements.txt
The true power for dependency management, however, lies in using uv with a pyproject.toml file. You can add dependencies using uv add, which is analogous to poetry add.
# Add a package and update the pyproject.toml
uv add pandas
# Add a development dependency
uv add --dev pytest
Locking Dependencies and Reproducible Installs
For reproducible builds, you must “lock” your dependencies. The uv lock command generates a uv.lock file, which pins every transitive dependency to an exact version. This is the equivalent of pip-compile from pip-tools.
# Generate or update the uv.lock file based on pyproject.toml
uv lock
To install dependencies exactly as specified in the lock file, use the --locked flag. This ensures that every installation, whether on a developer’s machine or in a CI/CD pipeline, is identical.
# Install dependencies strictly from the uv.lock file
uv sync --locked
Managing Python Versions
Beyond package management, uv can download and manage multiple Python versions, similar to pyenv. This feature allows you to easily test your project against different interpreters without relying on system-wide installations.
# List available Python versions
uv python list
# Install Python 3.12.3
uv python install 3.12.3
# Use a specific installed Python version to create a virtual environment
uv venv --python 3.12.3 .venv
Common Pitfalls and Best Practices
A common pitfall is forgetting that uv venv and uv pip are distinct commands. You must create or activate a virtual environment before using uv pip install to avoid installing packages into the system Python. Always run uv venv first in a new project directory.
Best practice involves always using a pyproject.toml file and the uv add command to manage dependencies declaratively. This keeps your direct dependencies clearly documented. Furthermore, always use uv sync --locked in production and CI environments. This guarantees that the installed packages are precisely those resolved when the uv.lock file was created, preventing unforeseen breaks due to a dependency releasing a new version. Finally, remember that uv.lock should be committed to your version control system; it is the blueprint for a reproducible environment.
Verifying Your Installation and the python vs python3 Confusion
After successfully installing Python, the crucial next step is verifying that the installation is both complete and functional. This process also introduces one of the most common points of confusion for newcomers and experienced developers alike: the distinction between the python and python3 commands. This discrepancy is not an error but a deliberate design choice to manage multiple Python versions on a single system.
Verifying Your Python Installation
To confirm that Python is installed correctly and accessible from your command line, you must open a terminal (Command Prompt or PowerShell on Windows, Terminal on macOS/Linux) and check the version. The command you use depends on your operating system and how Python was installed.
On most Windows systems following a standard installer from python.org, the python command is made available. You should run:
python --version
On macOS, Linux, and some Windows environments, you may need to use the more explicit python3 command to ensure you are targeting Python 3.x and not a legacy Python 2.7 installation that might still be present on the system.
python3 --version
A successful response will be a single line output showing the version number, e.g., Python 3.12.1. If you receive a “‘python’ is not recognized as an internal or external command” error (or similar), this indicates that the Python installation directory was not added to your system’s PATH environment variable. You must rectify this by reinstalling Python and ensuring the “Add python.exe to PATH” checkbox is selected, or by manually adding the installation path (e.g., C:\Users\YourUser\AppData\Local\Programs\Python\Python312) to your PATH.
Understanding the python vs. python3 Dichotomy
The coexistence of python and python3 commands is a direct result of Python’s major version transition from 2.x to 3.x. Because Python 3 introduced backward-incompatible changes, both versions needed to run simultaneously on many systems during the long migration period. To avoid conflicts, the convention emerged: the python command could point to Python 2.x, while the new python3 command would explicitly point to a Python 3.x interpreter.
This convention is still prevalent on many Linux distributions and macOS systems, which often have a system-critical Python 2.7 installation that is invoked with python. On modern Windows installations and some Linux setups where only Python 3 is present, the python command is typically configured to point to Python 3. You can investigate this on your own system using the which (or where on Windows) command to see the full path of the executable being called.
# On macOS/Linux:
which python
which python3
# On Windows Command Prompt:
where python
where python3
Checking the Full Version Information
The --version flag is useful for a quick check, but for a more comprehensive overview, use the -V (capital V) flag for the same result, or launch the Python interpreter interactively. The interactive mode provides the full version string, including the build date and compiler information, which can be essential for debugging platform-specific issues.
python3 -V
# Output: Python 3.12.1
# Launch the interactive interpreter for more details
python3
Upon running the interactive command, you will be greeted with a prompt that looks like >>>, and the header will display detailed information:
Python 3.12.1 (main, Jan 10 2024, 12:45:05) [GCC 11.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>>
You can exit the interactive interpreter by typing exit() and pressing Enter, or by pressing Ctrl-D (on macOS/Linux) or Ctrl-Z (on Windows).
Best Practices and Script Shebangs
For maximum clarity and cross-platform compatibility, especially in shell scripts and automation, it is considered a best practice to explicitly use python3 in your terminal commands and scripts. This eliminates any ambiguity about which version should be executed.
When writing executable Python scripts on Unix-like systems (macOS, Linux), the first line (called a shebang) should explicitly specify the python3 interpreter. This tells the shell exactly which program to use to run the script, making the script self-contained and version-aware.
#!/usr/bin/env python3
# The above line is the shebang
print("This script will always run with Python 3!")
To make the script executable, you would use chmod +x script.py. You can then run it with ./script.py, and the system will use the python3 interpreter found in your PATH. This practice is a robust solution to the version ambiguity problem and is highly recommended for all your scripts.
System Python vs User Python: What to Avoid and Why
On many systems, particularly those running Linux or macOS, a version of Python is pre-installed. This is known as the system Python. It is deeply integrated into the operating system’s functionality; core system tools and package managers (like yum on older Red Hat systems or apt on Debian/Ubuntu) often rely on specific Python scripts to function correctly. Because of this critical role, the system Python is managed by the system’s package manager and should be treated as a read-only resource. Modifying it can lead to catastrophic system instability, broken dependencies, and a non-functional administrative environment.
The primary risk lies in altering its environment. If you use pip to install, upgrade, or uninstall a package for the system Python, you might inadvertently upgrade a core system utility (e.g., python3-apt) or remove a dependency that a system script requires. This action can create a version conflict that the system’s package manager cannot resolve, potentially leaving you unable to install new software or even update your system.
# !!! DANGER: DO NOT DO THIS !!!
# This is an example of what can break your system.
sudo pip3 install --upgrade pip setuptools
# A system tool might depend on a specific, older version of setuptools.
# Upgrading it globally can cause that tool to fail mysteriously.
Furthermore, the system Python’s interpreter is often located in a protected directory like /usr/bin/python3. Installing packages to its site-packages directory (/usr/lib/python3/dist-packages/) requires sudo privileges, running arbitrary code from the Python Package Index (PyPI) with root-level access. This is a significant security risk, as a malicious package could compromise the entire system.
The Solution: User-Level Python Installations
The unequivocal best practice for developers is to avoid the system Python entirely for development work and instead use a user-level Python installation. This is a separate Python interpreter installed in your user’s home directory (e.g., ~/.pyenv/versions/ or ~/anaconda3/) or managed by a version manager. This isolation creates a clear boundary: the system Python remains pristine for the OS to use, and your user Python becomes a sandbox for your projects, development, and experimentation.
The key advantage is that you have complete control over this environment without needing sudo. You can install any package, change interpreter versions, and modify the environment without any risk to the underlying operating system. This approach also enables you to maintain multiple, project-specific environments with different dependencies, a concept central to modern Python development.
Using a Version Manager (pyenv)
The most robust method for managing user-level Python installations is with a dedicated version manager like pyenv. It automates the process of downloading, compiling, and switching between multiple Python versions seamlessly.
# Install pyenv (typically done via a git clone, see pyenv.github.io for instructions)
# List all available Python versions for installation
pyenv install --list
# Install a specific version, e.g., Python 3.12.3
# This compiles it from source and places it in ~/.pyenv/versions/
pyenv install 3.12.3
# Set the global default Python for your user account to the newly installed version
pyenv global 3.12.3
# Verify the change. The 'which' command should now point to a shim in ~/.pyenv/shims/
which python3
python3 --version
pyenv works by using “shim” executables that intercept commands like python and pip. These shims determine the correct version of Python to use based on your shell’s current context (global, local directory, or shell session) and route the command accordingly. This is why the path to python changes after setting a global version.
Using the Built-in venv Module
Even with a user-level Python interpreter, it’s bad practice to install all project packages into a single global site-packages directory. This can lead to dependency conflicts between projects. The solution is to use virtual environments, and Python’s built-in venv module is the standard tool for creating them.
# Create a new virtual environment in a directory named '.venv'
python3 -m venv .venv
# Activate the environment (the command differs by shell)
# On macOS/Linux (bash/zsh):
source .venv/bin/activate
# On Windows (Command Prompt):
.venv\Scripts\activate.bat
# On Windows (PowerShell):
.venv\Scripts\Activate.ps1
# Your shell prompt will change, indicating you are now inside the virtual environment.
# Now, 'python' and 'pip' point to the virtual environment's copies.
pip install requests # This installs 'requests' only inside .venv
python -c "import requests; print(requests.__version__)"
# To deactivate and return to your normal shell
deactivate
A virtual environment is a self-contained directory that contains a copy of the Python interpreter, the pip package manager, and a separate site-packages folder. When activated, it temporarily prepends this environment’s bin directory to your PATH variable. This ensures that when you type python or pip, you are using the isolated environment’s binaries, completely shielding your user-level and system-level Python installations from any changes made while the environment is active.