Skip to content

Updating requirements.txt using uv

Problem Statement

When using uv for Python dependency management, you may update your uv.lock file after modifying pyproject.toml but find that your requirements.txt file remains outdated despite running the uv pip compile command. This commonly occurs in workflows where:

  1. Production environments use pip and requirements.txt for deployments
  2. Local development uses uv with pyproject.toml and uv.lock
  3. After running uv lock --upgrade to update lock files, requirements.txt fails to reflect the latest package versions when generated

The core issue is that uv pip compile resolves dependencies directly from pyproject.toml rather than using the updated information in uv.lock. This results in outdated package versions persisting in requirements.txt.

Solution 1: Export dependencies from lock file (Standard approach)

Use uv export to generate requirements.txt directly from your uv.lock file:

bash
# Basic export without hashes
uv export > requirements.txt

# Export without hashes (pip-compatible)
uv export --format requirements-txt-no-hashes > requirements.txt

# Export with hashes (secure production version)
uv export --format requirements-txt > requirements.txt

# Exclude development dependencies
uv export --format requirements-txt-no-hashes --no-dev > requirements.txt

Key flags:

  • --format: Controls hash inclusion (requirements-txt includes hashes)
  • --no-dev: Excludes development dependencies
  • --no-header: Omits explanatory header text
  • > requirements.txt: Redirects output to file

Solution 2: Freeze installed packages (Environment-based)

Generate requirements.txt from your current virtual environment:

bash
uv pip freeze > requirements.txt

WARNING

This approach requires:

  1. An active virtual environment
  2. All dependencies to be installed with uv pip install
  3. The environment to match your uv.lock contents exactly

Solution 3: Compile without resolving dependencies (Edge cases)

Compile requirements while skipping dependency resolution (use when needing exact package specifications):

bash
uv pip compile pyproject.toml --output-file requirements.txt --no-deps

when to use this

Only suitable when:

  • You need exact package pins without dependencies
  • Your pyproject.toml contains full version specifications
  • You're intentionally avoiding dependency resolution

Why Your Initial Command Failed

bash
uv pip compile pyproject.toml --output-file requirements.txt

This reads directly from pyproject.toml and performs a new dependency resolution operation, ignoring:

  • Existing uv.lock updates
  • Previously upgraded package versions
  • Changes made by uv lock --upgrade

The command effectively regenerates requirements from original source constraints rather than respecting your lock file updates.

Best Practices

  1. Consistent lock file usage
    Maintain a single source of truth via uv.lock and export directly from it

  2. Hash inclusion for production
    Always include hashes in production artifacts for dependency integrity:

    bash
    uv export --format requirements-txt > requirements.prod.txt
  3. Dev/production separation
    Use different files for development and production dependencies:

    bash
    # Production
    uv export --no-dev --format requirements-txt > requirements.txt
    
    # Development
    uv export --format requirements-txt > requirements-dev.txt
  4. Optimized workflow
    Combine lock updating with requirements export:

    bash
    uv lock --upgrade && uv export --no-dev > requirements.txt

TIP

For CI/CD pipelines, include the full export command instead of committing requirements.txt to source control. Install dependencies directly using:

bash
uv pip install -r requirements.txt

By using uv export as your primary requirements generation method, you ensure consistency between your lock files and production requirements while maintaining compatibility with pip-based deployment environments.