Skip to content

Python Environment Management — venv, Poetry, uv, and pip-tools

DodaTech Updated 2026-06-29 5 min read

In this tutorial, you will learn about Python Environment Management. We cover key concepts, practical examples, and best practices to help you master this topic.

Managing Python environments is essential for reproducible development and deployment. The ecosystem has evolved from basic virtualenv to sophisticated tools like Poetry and the blazing-fast uv. Choosing the right tool depends on your workflow, team size, and deployment requirements.

DodaTech uses Poetry for library development and pip-tools for deployment, ensuring reproducible builds across development, CI, and production.

What You'll Learn

  • venv: Python's built-in virtual environment manager
  • pip-compile and pip-sync from pip-tools
  • Poetry: modern dependency management and packaging
  • uv: ultra-fast pip/venv replacement
  • Conda for Data Science environments
  • Docker for production isolation
  • Best practices for reproducible environments

venv — Python's Built-in Solution

# Create a virtual environment
python -m venv .venv

# Activate (Linux/Mac)
source .venv/bin/activate

# Activate (Windows)
# .venv\Scripts\activate

# Install packages
pip install requests flask

# Freeze requirements
pip freeze > requirements.txt

# Deactivate
deactivate

# On another machine / in CI:
python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt

venv Best Practices

# Use .venv (hidden directory, conventional name)
python -m venv .venv

# Always pin Python version
# .python-version:
3.12

# Prefer pip's new resolver (default since pip 21.3)
pip install --use-feature=resolver packages.txt

# Upgrade pip first
pip install --upgrade pip

pip-tools — Reproducible Pinning

pip install pip-tools
# requirements.in (direct dependencies only)
requests>=2.31
flask>=3.0
pandas
# Generate pinned requirements.txt
pip-compile requirements.in

# Output: requirements.txt with exact versions (pinned)
# requests==2.31.0
#   -- certifi==2024.2.2
#   -- charset-normalizer==3.3.2
#   ...
# flask==3.0.1
# pandas==2.2.0
#   -- numpy==1.26.4
#   ...

# Sync environment exactly
pip-sync requirements.txt

# Compile for different Python versions
pip-compile --python-version 3.11 requirements.in

# Upgrade specific package
pip-compile --upgrade-package requests requirements.in

Multiple Environments

# requirements.in (production deps)
flask
gunicorn

# dev-requirements.in (development deps)
-c requirements.txt  # pin to production versions
pytest
pytest-cov
black
ruff
pip-compile requirements.in
pip-compile dev-requirements.in
pip-sync requirements.txt dev-requirements.txt

Poetry — Modern All-in-One

# Install Poetry
curl -sSL https://install.python-poetry.org | python3 -

# Or via pip
pip install poetry
# Create new project
poetry new my-project
cd my-project

# Or initialize existing project
poetry init

# Add dependencies
poetry add requests flask
poetry add --group dev pytest black ruff

# Install all dependencies
poetry install

# Install only production
poetry install --only main

# Create and activate venv automatically
poetry shell

# Run command in venv
poetry run python my_script.py
# pyproject.toml
[tool.poetry]
name = "my-project"
version = "0.1.0"
description = ""
authors = ["Your Name <you@example.com>"]
readme = "README.md"
packages = [{ include = "my_project" }]

[tool.poetry.dependencies]
python = ">=3.11,<3.13"
requests = "^2.31"
flask = "^3.0"

[tool.poetry.group.dev.dependencies]
pytest = "^8.0"
ruff = "^0.3"

[build-system]
requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api"

Publishing to PyPI

# Build
poetry build

# Publish
poetry config pypi-token.pypi your-token
poetry publish

uv — Ultra-Fast Package Manager

# Install
pip install uv

# Create venv and install (10-100x faster than pip)
uv venv .venv
uv pip install requests flask

# Using requirements.txt
uv pip install -r requirements.txt

# Compile requirements
uv pip compile requirements.in -o requirements.txt

# Sync
uv pip sync requirements.txt

# Why uv is fast:
# - Written in Rust
# - Parallel downloads
# - Global cache
# - Avoids intermediate wheel files

Conda for Data Science

# Install Miniconda
# https://docs.conda.io/en/latest/miniconda.html

# Create environment
conda create -n myenv python=3.12

# Activate
conda activate myenv

# Install packages
conda install numpy pandas matplotlib
conda install -c conda-forge scipy

# Export environment
conda env export > environment.yaml

# Recreate
conda env create -f environment.yaml

# List environments
conda env list

Docker for Production

FROM python:3.12-slim AS builder

WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

FROM python:3.12-slim

WORKDIR /app
COPY --from=builder /usr/local/lib/python3.12/site-packages /usr/local/lib/python3.12/site-packages
COPY . .

CMD ["python", "app.py"]
# Multi-stage with Poetry
FROM python:3.12-slim AS builder

RUN pip install poetry
WORKDIR /app
COPY pyproject.toml poetry.lock ./
RUN poetry export -f requirements.txt --output requirements.txt --without-hashes
RUN pip install --no-cache-dir -r requirements.txt

FROM python:3.12-slim
WORKDIR /app
COPY --from=builder /usr/local/lib/python3.12/site-packages /usr/local/lib/python3.12/site-packages
COPY . .
CMD ["python", "app.py"]

Best Practices

# 1. Always use virtual environments (never pip install system-wide)

# 2. Pin your Python version
# .python-version:
3.12.2

# 3. Separate dev and production dependencies
pip-compile requirements.in
pip-compile dev-requirements.in

# 4. Lock files in version control
# Commit: requirements.txt, poetry.lock, Pipfile.lock

# 5. Use hashes for security (pip)
pip-compile --generate-hashes requirements.in

# 6. CI/CD pattern
python -m venv .venv
source .venv/bin/activate
pip install --upgrade pip
pip install -r requirements.txt

# 7. Regular updates
pip-compile --upgrade requirements.in

Practice Questions

  1. Create a Python project with Poetry, add three dependencies and one dev dependency.

  2. Use pip-tools to create a requirements.txt with hashes for a Flask project.

  3. Compare installation time of pip vs uv for the same set of 10 packages.

  4. Write a Dockerfile for a Python app using multi-stage builds.

  5. Set up a CI pipeline that caches the virtual environment for faster builds.

Challenge: Multi-Environment Build System

Create a Makefile (or Justfile) that manages multiple environments:

make install       # Install production deps
make install-dev   # Install dev + production deps
make update        # Update all dependencies
make freeze        # Pin current versions
make clean         # Remove virtual env
make test          # Run tests in clean environment
make build         # Build package
make ci            # Full CI pipeline (clean → install-dev → test → build)

This is the setup DodaTech uses across all its Python services — a unified Makefile interface that works the same in development, CI, and deployment.

Real-World Task: Reproducible Deployment Package

Create a script that validates and packages a Python project for deployment:

  1. Verify Python version matches requirements
  2. Check for known vulnerabilities in dependencies (pip-audit)
  3. Verify lock file is up to date
  4. Build the package with all dependencies vendored
  5. Generate a manifest with checksums
  6. Package into a deployable artifact (Docker image or zip)

This is the deployment pipeline DodaTech uses to ensure every deployment is reproducible, auditable, and free of known vulnerabilities.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro