# Python Dependency Management Advanced patterns for managing Python dependencies with uv. ## Lock File Workflow ### Basic Lock Pattern ```bash # requirements.in (loose constraints) flask>=2.0 sqlalchemy>=2.0 pydantic>=2.0 # Generate locked requirements.txt uv pip compile requirements.in -o requirements.txt # Install exact versions uv pip sync requirements.txt ``` ### Separate Dev Dependencies ```bash # requirements.in flask>=2.0 sqlalchemy>=2.0 # requirements-dev.in -r requirements.in pytest>=7.0 ruff>=0.1 mypy>=1.0 # Compile both uv pip compile requirements.in -o requirements.txt uv pip compile requirements-dev.in -o requirements-dev.txt # Install for development uv pip sync requirements-dev.txt ``` ### Update Workflow ```bash # Update all packages to latest compatible versions uv pip compile requirements.in -o requirements.txt --upgrade # Update specific package uv pip compile requirements.in -o requirements.txt --upgrade-package flask # Update with constraints uv pip compile requirements.in -o requirements.txt --upgrade --constraint constraints.txt ``` ## Constraint Files ```bash # constraints.txt # Pin versions that need to be consistent across projects numpy==1.26.0 pandas==2.0.0 # Use constraints during compile uv pip compile requirements.in -o requirements.txt --constraint constraints.txt ``` ## Multiple Environments ### Python Version Specific ```bash # Python 3.10 uv pip compile requirements.in -o requirements-py310.txt --python-version 3.10 # Python 3.11 uv pip compile requirements.in -o requirements-py311.txt --python-version 3.11 ``` ### Platform Specific ```bash # Linux uv pip compile requirements.in -o requirements-linux.txt --platform linux # macOS uv pip compile requirements.in -o requirements-macos.txt --platform macos # Windows uv pip compile requirements.in -o requirements-windows.txt --platform windows ``` ## Workspace/Monorepo ### Structure ``` my-monorepo/ ├── pyproject.toml # Root workspace config ├── packages/ │ ├── core/ │ │ └── pyproject.toml │ ├── api/ │ │ └── pyproject.toml │ └── cli/ │ └── pyproject.toml ``` ### Root pyproject.toml ```toml [tool.uv.workspace] members = ["packages/*"] [tool.uv.sources] my-core = { workspace = true } my-api = { workspace = true } ``` ### Package pyproject.toml ```toml # packages/core/pyproject.toml [project] name = "my-core" version = "0.1.0" dependencies = ["pydantic>=2.0"] # packages/api/pyproject.toml [project] name = "my-api" version = "0.1.0" dependencies = ["my-core", "fastapi>=0.100"] ``` ### Workspace Commands ```bash # Install all workspace packages uv pip install -e packages/core -e packages/api -e packages/cli # Sync entire workspace uv sync # Run command in workspace context uv run pytest ``` ## Private Packages ### Configure Index ```bash # Extra index for private packages uv pip install my-private-package --extra-index-url https://pypi.private.com/simple/ # With authentication uv pip install my-private-package \ --extra-index-url https://user:token@pypi.private.com/simple/ ``` ### In requirements.in ``` --extra-index-url https://pypi.private.com/simple/ my-public-package>=1.0 my-private-package>=2.0 ``` ### Environment Variable ```bash export UV_EXTRA_INDEX_URL=https://user:token@pypi.private.com/simple/ uv pip install my-private-package ``` ## Git Dependencies ```toml # In pyproject.toml [project] dependencies = [ "my-package @ git+https://github.com/user/repo.git", "my-package @ git+https://github.com/user/repo.git@v1.0.0", "my-package @ git+https://github.com/user/repo.git@main", "my-package @ git+ssh://git@github.com/user/repo.git", ] ``` ```bash # requirements.in git+https://github.com/user/repo.git@main#egg=my-package ``` ## Local Dependencies ```toml # In pyproject.toml [project] dependencies = [ "my-local @ file:///path/to/package", ] # Relative path [tool.uv.sources] my-local = { path = "../my-local-package" } ``` ## Dependency Resolution ### Resolver Options ```bash # Use backtracking resolver (more thorough but slower) uv pip compile requirements.in -o requirements.txt --resolver=backtracking # Allow prereleases uv pip compile requirements.in -o requirements.txt --prerelease=allow # Exclude specific packages from upgrade uv pip compile requirements.in -o requirements.txt --upgrade --no-upgrade-package numpy ``` ### Resolution Troubleshooting ```bash # Show why a version was chosen uv pip compile requirements.in --verbose # Generate dependency tree uv pip tree # Check for conflicts uv pip check ``` ## Caching ```bash # Clear uv cache uv cache clean # Show cache location uv cache dir # Disable cache for one command uv pip install --no-cache package-name ``` ## CI/CD Patterns ### GitHub Actions ```yaml - name: Install uv uses: astral-sh/setup-uv@v1 with: version: "latest" - name: Install dependencies run: | uv venv uv pip sync requirements.txt - name: Run tests run: uv run pytest ``` ### Cache Dependencies ```yaml - name: Cache uv uses: actions/cache@v3 with: path: ~/.cache/uv key: uv-${{ hashFiles('requirements.txt') }} restore-keys: uv- ``` ### Lock File in CI ```yaml - name: Verify lock file is up to date run: | uv pip compile requirements.in -o requirements-check.txt diff requirements.txt requirements-check.txt ``` ## Best Practices 1. **Always use lock files in production** - Reproducible builds 2. **Separate dev dependencies** - Smaller production installs 3. **Use constraints for shared deps** - Consistent versions across packages 4. **Pin Python version** - Avoid compatibility surprises 5. **Run `uv pip check`** - Catch conflicts early 6. **Cache in CI** - Faster builds 7. **Review upgrades carefully** - Don't blindly `--upgrade`