Python virtual environments solve a fundamental dependency management problem: different projects require different versions of the same library, and installing everything system-wide leads to version conflicts. A virtual environment is a self-contained directory containing a Python interpreter copy and a site-packages directory isolated from the system Python. Each project gets its own virtual environment with its own independent set of packages. When the virtual environment is activated, python and pip refer to the environment’s copies rather than the system-wide ones. The built-in venv module (included since Python 3.3) creates virtual environments without any additional tools. This guide covers creating, activating, and managing Python virtual environments on RHEL 9, including generating reproducible requirements.txt files for deployment.
Prerequisites
- Python 3 installed on RHEL 9
Step 1 — Create a Virtual Environment
mkdir /var/www/myproject && cd /var/www/myproject
# Create a virtual environment in the .venv directory
python3.12 -m venv .venv
# Or with the system python3
python3 -m venv .venv
ls -la .venv/
Step 2 — Activate the Virtual Environment
# Bash/Zsh (interactive development)
source .venv/bin/activate
# Verify: the prompt shows (.venv) prefix and python points to the venv
which python # → /var/www/myproject/.venv/bin/python
python --version
pip --version
Step 3 — Install Project Dependencies
# With venv activated:
pip install flask sqlalchemy psycopg2-binary python-dotenv
# Generate a pinned requirements file for reproducible installs
pip freeze > requirements.txt
cat requirements.txt
Step 4 — Install from requirements.txt
# Recreate the environment on a new server (production deployment)
python3.12 -m venv .venv
source .venv/bin/activate
pip install --upgrade pip
pip install -r requirements.txt
Step 5 — Using the Venv Without Activation (for systemd)
# systemd services should use the venv's python directly — no activation needed
# /etc/systemd/system/myapp.service
[Unit]
Description=My Python Application
After=network.target
[Service]
User=myapp
WorkingDirectory=/var/www/myproject
ExecStart=/var/www/myproject/.venv/bin/python app.py
Restart=always
Environment=PYTHONUNBUFFERED=1
[Install]
WantedBy=multi-user.target
Step 6 — Deactivate and Delete
# Deactivate the current venv
deactivate
# Delete a virtual environment (all packages removed)
rm -rf .venv
# Recreate from requirements.txt
python3.12 -m venv .venv && source .venv/bin/activate && pip install -r requirements.txt
Conclusion
Python virtual environments on RHEL 9 are the standard practice for isolating project dependencies. Always add .venv/ to your .gitignore — the virtual environment directory should never be committed to version control since it contains OS-specific compiled binaries. Instead, commit requirements.txt (pinned versions from pip freeze) and recreate the environment during deployment. For systemd services, reference the virtual environment’s Python binary directly (/path/to/.venv/bin/python) to avoid activation script complications.
Next steps: How to Install Python 3 on RHEL 9, How to Deploy a Flask Application on RHEL 9, and How to Deploy a Django Application on RHEL 9.