Fullmoon System

Python venv Guide: Creation, Activation, requirements.txt, and Production Use

EdwardMoon

Python venv separates the package installation space for each project. It is part of the Python standard library. Installing packages directly into the system Python can create version conflicts with OS tools or other applications; virtual environments let each project manage the versions it needs independently.

This practical guide covers creating and checking virtual environments on Linux, macOS, and Windows, then managing requirements.txt, offline wheelhouses, systemd services, safe removal, and troubleshooting. Before copying commands, adjust the Python version and project paths to match your environment.

Python venv: separate project package environments based on one base Python installation
Virtual environments separate project package installations while using a shared base Python

Python venv Quick Start

The simplest pattern is to create .venv inside the project directory and run pip through that environment's Python. Using python -m pip instead of a bare pip command makes it clear that pip belongs to the selected interpreter.

mkdir -p ~/projects/sample-app
cd ~/projects/sample-app

python3 --version
python3 -m venv .venv
source .venv/bin/activate

python -m pip --version
python -m pip install --upgrade pip
python -m pip install requests
python -c "import requests; print(requests.__version__)"

deactivate
A virtual environment directory is not source code. Keep .venv/ out of Git and use dependency files so it can be recreated whenever needed.

What venv Is and What It Isolates

A Separate Execution Context, Not a Complete Python Clone

Creating a virtual environment adds pyvenv.cfg, an executable directory, and a separate site-packages directory to the target location. Depending on the platform and creation options, the Python executable may be a copy or a symbolic link. venv therefore does not isolate the OS as a container does; it depends on the base Python used to create it and on operating system libraries.

python3 -m venv .venv

find .venv -maxdepth 2 -type f -o -type l | sort | head -30
cat .venv/pyvenv.cfg

Reliably Check Whether Python Is Running in a Virtual Environment

The activation script prepends the environment's executable directory to PATH. Activation is optional, however, so checking VIRTUAL_ENV alone can miss some cases. Within Python, comparing sys.prefix with sys.base_prefix is more reliable.

python - <<'PY'
import sys

print("executable   :", sys.executable)
print("prefix       :", sys.prefix)
print("base_prefix  :", sys.base_prefix)
print("inside venv  :", sys.prefix != sys.base_prefix)
PY

Checks Before Creating a venv

First identify the exact Python executable and version, and check whether the venv module and pip bootstrapping are available. If multiple Python versions are installed, explicitly select the interpreter, such as python3.11, when creating the environment.

command -v python3
python3 --version
python3 -m venv --help >/dev/null
python3 -m ensurepip --version

Some Linux distributions package venv or pip separately. Package names vary by distribution and Python version, so check the repositories before installing. Avoid using sudo pip install with the system Python.

# A typical example for Debian and Ubuntu
sudo apt update
sudo apt install python3-venv python3-pip

# On RHEL and Rocky, first check which packages are available
sudo dnf list --available 'python3*' | grep -E 'pip|virtualenv'

Creation and Activation Commands by OS and Shell

Environment Create Activate
Linux/macOS bash·zsh python3 -m venv .venv source .venv/bin/activate
Linux/macOS fish python3 -m venv .venv source .venv/bin/activate.fish
Windows cmd py -m venv .venv .venv\Scripts\activate.bat
Windows PowerShell py -m venv .venv .venv\Scripts\Activate.ps1

After activation, verify the path and version. The (.venv) prompt is only a convenience indicator; checking the actual interpreter path helps prevent installations into the wrong environment.

command -v python
python --version
python -m pip --version
python -c "import sys; print(sys.executable)"

Use a venv Without Activating It

You do not need to run source to use a Python venv. In cron, systemd, and CI jobs, invoking the absolute path to the environment's Python is more predictable and easier to diagnose than relying on an activation script.

# Linux/macOS
/opt/sample-app/.venv/bin/python /opt/sample-app/app.py
/opt/sample-app/.venv/bin/python -m pip list

# Windows PowerShell
.\.venv\Scripts\python.exe .\app.py

Install Packages and Manage requirements.txt

Always Run pip Through the Intended Python

python -m pip install --upgrade pip
python -m pip install 'requests>=2.32,<3'
python -m pip list
python -m pip check

pip check verifies that installed packages' declared dependencies are compatible. Run it alongside application tests after installation to detect missing or conflicting dependencies early.

Capture and Reproduce an Environment

pip freeze lists the installed versions of direct and transitive dependencies, making it useful for recording a production environment. The same file may not install unchanged on a different OS, CPU architecture, or Python version, so record the runtime conditions as well.

python -m pip freeze > requirements.txt
python -m pip check

# Reproduce the installation in a new environment
python3 -m venv .venv-new
.venv-new/bin/python -m pip install --upgrade pip
.venv-new/bin/python -m pip install -r requirements.txt
.venv-new/bin/python -m pip check

Files to Keep in the Project

# .gitignore
.venv/
__pycache__/
*.py[cod]
.env

# Record versions and installed packages
python --version
python -m pip --version
python -m pip freeze

Use Python venv in Air-Gapped and Offline Environments

For offline deployment, match the online preparation server to the target's OS, CPU architecture, and Python major and minor version. Wheels can depend on the platform and Python ABI, so simply copying downloads from another PC may fail.

Prepare a Wheelhouse on the Online Server

python3 -m venv bundle-venv
bundle-venv/bin/python -m pip install --upgrade pip

# Allowing only wheels reveals packages that would otherwise require an offline source build.
bundle-venv/bin/python -m pip download   --only-binary=:all:   --dest wheelhouse   -r requirements.txt

sha256sum wheelhouse/* > SHA256SUMS
tar -czf python-wheelhouse.tar.gz wheelhouse requirements.txt SHA256SUMS
sha256sum python-wheelhouse.tar.gz > python-wheelhouse.tar.gz.sha256

Verify and Install on the Offline Server

sha256sum -c python-wheelhouse.tar.gz.sha256
tar -xzf python-wheelhouse.tar.gz

sha256sum -c SHA256SUMS

python3 -m venv .venv
.venv/bin/python -m pip install   --no-index   --find-links=wheelhouse   -r requirements.txt
.venv/bin/python -m pip check

A package that fails with --only-binary=:all: has no compatible wheel available from the selected source. Build a wheel on the online build server with the necessary compiler and development headers, then create a fresh environment on a matching test server and verify both installation and execution.

Use a venv in a systemd Service

systemd is not an interactive shell, so there is no need to run source .venv/bin/activate. Specify the absolute Python path in ExecStart and keep secrets in a permission-restricted file separate from source code.

# /etc/systemd/system/sample-app.service
[Unit]
Description=Sample Python application
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
User=sampleapp
Group=sampleapp
WorkingDirectory=/opt/sample-app
EnvironmentFile=/etc/sample-app/sample-app.env
ExecStart=/opt/sample-app/.venv/bin/python /opt/sample-app/app.py
Restart=on-failure
RestartSec=5
NoNewPrivileges=true
PrivateTmp=true

[Install]
WantedBy=multi-user.target
sudo systemd-analyze verify /etc/systemd/system/sample-app.service
sudo systemctl daemon-reload
sudo systemctl enable --now sample-app.service
sudo systemctl status sample-app.service --no-pager
sudo journalctl -u sample-app.service -n 100 --no-pager

Why You Should Recreate a venv Instead of Moving It

The shebang in an installed script may contain the absolute path to its environment's interpreter. Copying the directory elsewhere or to another server can break that path, so do not treat the venv itself as a deployment artifact. The officially recommended approach is to create an environment at the new location and reinstall packages from dependency files or a wheelhouse.

# Record the existing environment's runtime details and dependencies
.venv/bin/python --version
.venv/bin/python -m pip freeze > requirements.txt

# Recreate the environment at the new location
python3 -m venv /opt/sample-app/.venv
/opt/sample-app/.venv/bin/python -m pip install -r requirements.txt
/opt/sample-app/.venv/bin/python -m pip check

Remove a venv Safely

Removing a virtual environment means deleting its directory, but a mistyped variable or empty path can delete unrelated data. Check the absolute path and pyvenv.cfg first, and confirm that no running service uses the environment.

# This block runs in a subshell, so canceling will not exit your login shell.
(
  set -eu
  VENV="$(realpath -e -- .venv)"
  test -d "$VENV" && test -f "$VENV/pyvenv.cfg" || {
    echo '가상환경 디렉터리가 아니므로 중단합니다.' >&2
    exit 1
  }
  case "$VENV" in /|"$HOME"|/opt|/usr|/var)
    echo '삭제할 수 없는 상위 경로입니다.' >&2; exit 1 ;;
  esac
  printf 'delete target: %s\n' "$VENV"
  grep -R --fixed-strings "$VENV" /etc/systemd/system /etc/cron* 2>/dev/null || true
  # Review the paths above and any running services or cron jobs before answering.
  read -r -p '이 경로만 삭제하려면 DELETE 입력: ' answer
  if [ "$answer" != DELETE ]; then
    echo '취소했습니다.'
    exit 0
  fi
  rm -rf -- "$VENV"
)
When replacing a production service's virtual environment, build and test a new one at a separate path before switching the service. Preserve the old directory so the service can be pointed back to it if needed.

Common Problems and Remedies

Symptom Check first Remedy
No module named venv The distribution's venv package Install the venv package matching your Python version from OS repositories
Import fails after installation sys.executable and python -m pip --version Reinstall through the same interpreter's pip
PowerShell blocks activation Execution policy and organizational security policy Use the absolute Python path or follow administrator guidance instead of weakening policy arbitrarily
A copied environment will not run Absolute paths in shebangs Recreate the environment at its new location and reinstall dependencies
Offline wheel installation fails OS, CPU, and Python ABI tags Rebuild the wheelhouse under conditions matching the target
pip dependency conflicts python -m pip check Resolve version constraints and test in a clean environment
python -c "import sys; print(sys.executable); print(sys.version)"
python -m pip --version
python -m pip list
python -m pip check
python -m site

Choosing Between venv, virtualenv, pipx, and conda

  • venv: A good fit for manually managing project environments using only the Python standard library.
  • virtualenv: Consider it when you need more creation options or broader Python compatibility features.
  • pipx: Suitable for installing Python CLI tools such as Black or Ansible Lint into their own environments while making their commands available globally.
  • conda: Common in scientific and data environments that need to manage native libraries as well as Python packages.

For ordinary server and development projects, starting with standard Python venv keeps dependency isolation simple. Choose another tool when a clear requirement, such as distributing CLI tools or managing native dependencies, calls for it.

Practical Checklist

  1. Verify the intended Python executable and version before creating the environment.
  2. Install packages with python -m pip and validate them with pip check.
  3. Exclude .venv/ from version control and retain requirements or lock files.
  4. Run production services with the absolute path to the environment's Python instead of an activation script.
  5. Recreate virtual environments at the target location rather than copying or moving them.
  6. Build offline bundles under matching OS, CPU, and Python conditions, and verify SHA-256 checksums.
  7. Before removal, check the resolved path, pyvenv.cfg, and references from services or cron jobs.

Related Guides

Official References

Conclusion

The key to Python venv is not the activation command itself, but separating a project's interpreter and package paths and managing that environment reproducibly. Activate .venv for convenience during development, and use absolute paths in production automation. Managing dependency files, runtime conditions, integrity checks, and replacement procedures together makes venv reliable on both connected and air-gapped servers.