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 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
- Verify the intended Python executable and version before creating the environment.
- Install packages with
python -m pipand validate them withpip check. - Exclude
.venv/from version control and retain requirements or lock files. - Run production services with the absolute path to the environment's Python instead of an activation script.
- Recreate virtual environments at the target location rather than copying or moving them.
- Build offline bundles under matching OS, CPU, and Python conditions, and verify SHA-256 checksums.
- Before removal, check the resolved path,
pyvenv.cfg, and references from services or cron jobs.
Related Guides
Official References
- Official Python venv documentation
- PyPA: Installing packages with pip and virtual environments
- pip: Repeatable installs
- PyPA: Installing standalone CLI tools with pipx
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.