Dependency & Environment Conflicts
Environment bugs come from mismatched Python versions, divergent lockfiles, shadowed packages on PYTHONPATH, and editable installs pointing at the wrong checkout. Symptoms are import errors, ABI crashes, and tests that pass locally but fail in CI.
Recipe
Quick-reference recipe card - copy-paste ready.
python3 --version # expect 3.14.0 in prod-aligned envs
which python3
uv sync # install from uv.lock
uv run pytest
python -c "import mypkg; print(mypkg.__file__)"When to reach for this:
ModuleNotFoundErrorfor a package you "just installed"ImportError: DLL load failed/ incompatible binary wheels- CI fails while laptop passes (or vice versa)
- Two projects need conflicting versions of the same library
Working Example
# diagnose.sh - run from repo root
set -euo pipefail
echo "=== Python ==="
python3 --version
which python3
echo "=== Virtual env ==="
echo "${VIRTUAL_ENV:-not activated}"
echo "=== Lockfile install ==="
uv sync --frozen
echo "=== Package location ==="
uv run python -c "import orders; print(orders.__file__)"
echo "=== Installed dists (top) ==="
uv pip list | head -20
echo "=== pip check ==="
uv pip check# pyproject.toml - pin runtime and isolate groups
[project]
name = "orders"
requires-python = ">=3.14"
dependencies = ["fastapi>=0.115", "pydantic>=2"]
[dependency-groups]
dev = ["pytest>=8", "ruff>=0.9"]
[tool.uv]
dev-dependencies = ["pytest>=8", "ruff>=0.9"]# verify_imports.py - CI smoke
import importlib
import sys
REQUIRED = ("fastapi", "pydantic", "orders")
def main() -> None:
print("executable:", sys.executable)
print("version:", sys.version.replace("\n", " "))
for name in REQUIRED:
mod = importlib.import_module(name)
print(f"{name} -> {getattr(mod, '__file__', mod)}")
if __name__ == "__main__":
main()What this demonstrates:
- Version and path printed before debugging imports
uv sync --frozenfails if lockfile out of date withpyproject.tomlrequires-pythondocuments supported interpreter floor- Smoke import script catches wrong package on path early
Deep Dive
How It Works
- Virtual environments isolate
site-packagesper project - Lockfiles pin transitive versions; loose
pip installdoes not - Binary wheels tie to Python ABI tags (
cp314vscp313) - Editable installs (
-e .) symlink source; wrong cwd means wrong code
Conflict Checklist
| Signal | Likely cause | Fix |
|---|---|---|
| Old package despite upgrade | wrong venv active | deactivate; activate .venv |
Two versions in pip list | system + user site | pure venv; pip install --force-reinstall |
cpython-312 wheel on 3.14 | wrong wheel | regen lock on target Python |
| Import from unexpected path | PYTHONPATH shadow | remove; fix packaging |
| Poetry + uv mixed | two lock tools | standardize on uv 0.6+ |
Python Notes
# reproduce CI locally with container
docker run --rm -v "$PWD:/app" -w /app python:3.14.0-bookworm \
bash -lc "pip install uv && uv sync --frozen && uv run pytest"Gotchas
- Global
pip install- pollutes base Python; breaks other projects. Fix: venv per project; never install app deps globally. - Committed
.venv- platform-specific binaries in git. Fix: gitignore; documentuv syncin README. - Optional extras not installed in CI -
pip install .without[ml]extra missing torch. Fix: document extras; CI installs needed groups. - Different cwd in IDE test runner - imports local shadow module
json.py. Fix: rename shadows; src layout. - Stale editable install after rename - old package name cached. Fix: reinstall editable; clear
*.egg-link. - Conda + pip mixing - broken numpy/openssl ABIs. Fix: one tool per env; conda OR uv/pip stack.
Alternatives
| Alternative | Use When | Don't Use When |
|---|---|---|
uv lock + sync | fast reproducible envs | org mandates poetry only (bridge carefully) |
pip-tools compile | existing pip-tools shops | greenfield without constraint |
| Docker-only dev | strict prod parity | fast laptop iteration needed |
tox/nox matrices | multi-version libraries | single-version microservices |
FAQs
Why does uv sync fix "works on my machine"?
Everyone installs the same resolved graph from uv.lock on the same Python ABI. Drift shows up as lock mismatch instead of mystery imports.
Should CI use --frozen?
Yes in release pipelines. Fails when pyproject.toml changes without updating the lockfile, preventing silent upgrades.
How do I debug wrong module path?
python -c "import m; print(m.__file__)" and compare to expected site-packages or src/ editable path.
Can two projects share one venv?
Avoid it. Conflicting pins and import shadowing return. One venv per repo or use uv workspace with explicit members.
What if PyTorch CUDA wheels differ by machine?
Document optional extra indexes in README. CI CPU-only jobs install CPU index; GPU machines install platform-specific extra.
How do I pin Python 3.14 in Docker?
Use python:3.14.0-bookworm (or slim) and match requires-python in pyproject.toml.
Does ruff need the same venv?
Run ruff 0.9+ via uv run ruff so rules and auto-fixes see installed third-party stubs consistently.
How do I fix pip check failures?
uv pip check reports incompatible pins. Regenerate lock from a clean venv; remove manual pip install overrides in Dockerfile.
What about system Python on macOS?
Use python3 from .venv after uv venv. Homebrew/system Pythons are fine as base interpreters, not as install targets.
How do optional dependency groups help?
Keep heavy ML stacks optional ([project.optional-dependencies]) so API services do not install PyTorch in every image.
Can I delete uv.lock and regenerate?
Yes when upgrading major versions deliberately. Commit the new lock and run full CI matrix afterward.
How do IDE and CLI conflicts happen?
IDE points at different interpreter than terminal. Set workspace interpreter to .venv/bin/python explicitly.
Related
- Configuration & Settings - env vars vs packages
- src Layout & Package Structure - install before test
- Circular Import Scenarios - import errors that look like missing deps
- Codebase Audit Checklist - lockfile and audit items
- Debugging Tools - inspect sys.path in pdb
Stack versions: This page was written for Python 3.14.0 (stable 3.14, maintenance 3.13), FastAPI 0.115+, Django 5.2, Flask 3.1, Pydantic 2, PyTorch 2.6+, pandas 2.2+, Polars 1.x, ruff 0.9+, and uv 0.6+.