Diagnose and fix broken Python virtual environments, stale poetry locks, and pip issues.
Zero dependencies. Single file. Works when pip is broken.
python3 xnv.py fix # repairs venv without needing pipCommon Python environment failures:
| Problem | Cause | xnv solution |
|---|---|---|
pip: cannot execute: required file not found |
venv symlinks point to deleted/upgraded Python | Detect broken symlinks → recreate venv |
poetry.lock out of sync |
pyproject.toml edited without poetry lock |
Run poetry lock automatically |
| Conda + venv conflicts | PATH confusion between conda base and project venv | Detect CONDA_ACTIVE vs VIRTUAL_ENV mismatch |
pyvenv.cfg stale home |
System Python relocated after venv creation | Check pyvenv.cfg home dir exists |
| Broken pip shim | pip binary broken but python -m pip works |
Reinstall pip via ensurepip |
When pip is broken, you can't pip install a fix tool. xnv solves this by running as a single file with zero dependencies.
# 1. Download/copy xnv.py to your project
wget https://raw.githubusercontent.com/youruser/xnv/main/xnv.py
# or simply copy the file manually
# 2. Diagnose
python3 xnv.py # current directory
python3 xnv.py doctor /path/to/project # specific project
# 3. Fix auto-magically
python3 xnv.py fix # diagnose + repair + install deps
python3 xnv.py fix --force # force recreate venv
python3 xnv.py fix --no-install # repair only, skip pip install
# 4. Manual operations
python3 xnv.py nuke # remove venv completely
python3 xnv.py create # create fresh venv
python3 xnv.py lock # regenerate poetry.lockIf you want the xnv shortcut command:
# Development install (editable)
pip install -e .
# Or use pipx for isolated install
pipx install .
# Then use `xnv` instead of `python3 xnv.py`
xnv doctor
xnv fix$ python3 xnv.py doctor
xnv doctor — /home/user/myproject
✓ [VENV_PYTHON_OK] venv Python: Python 3.12.4
✓ [VENV_PIP_OK] venv pip: pip 24.0
⚠ [NO_PYPROJECT] No pyproject.toml found
✗ [POETRY_LOCK_STALE] poetry.lock out of sync with pyproject.toml
hint: poetry lock
1 errors / 1 warnings / 2 ok
✗ Issues found — run 'python3 xnv.py fix' to repairOptions:
--force, -f— Force recreate venv even if it appears healthy--no-install— Skip dependency installation (repair only)--dev— Install dev dependencies too (with Poetry)
# Standard repair
python3 xnv.py fix
# Force clean slate
python3 xnv.py fix --force
# Repair without installing packages
python3 xnv.py fix --no-installWhat fix does:
- Runs full diagnosis
- If poetry.lock stale →
poetry lock - If venv broken →
rm -rf venv && python3 -m venv venv - Upgrades pip in new venv
- Installs dependencies (Poetry preferred, pip fallback)
- Verifies the fix
python3 xnv.py nuke # remove ./venv
python3 xnv.py nuke --name .venv # remove ./.venvpython3 xnv.py create # create ./venv
python3 xnv.py create --name .venv # create ./.venv
python3 xnv.py create --force # recreate if existspython3 xnv.py lock # runs 'poetry lock'| Code | Severity | Description | Auto-fixed by fix? |
|---|---|---|---|
VENV_BROKEN_PYTHON |
error | Python symlink points to missing target | ✅ Yes |
VENV_NO_PYTHON |
error | Python binary missing from venv | ✅ Yes |
VENV_PYTHON_FAIL |
error | Python binary not executable | ✅ Yes |
VENV_BROKEN_PIP |
error | pip symlink broken | ✅ Yes |
VENV_NO_PIP |
error | pip binary missing | ✅ Yes (via ensurepip) |
VENV_PIP_FAIL |
error | pip not functional | ✅ Yes |
VENV_PIP_SHIM_BROKEN |
error | pip shim broken but python -m pip works |
✅ Yes (reinstall pip) |
VENV_STALE_HOME |
error | pyvenv.cfg home dir missing | ✅ Yes |
POETRY_LOCK_STALE |
error | poetry.lock out of sync | ✅ Yes |
VENV_MISMATCH |
warn | Active VIRTUAL_ENV ≠ project venv | ❌ Manual fix |
NO_VENV |
warn | No venv found | ✅ Yes (creates one) |
NO_PYPROJECT |
warn | No pyproject.toml | ❌ N/A |
POETRY_NO_LOCK |
warn | poetry.lock missing | ✅ Yes |
CONDA_ACTIVE |
info | Conda environment detected | — |
VENV_EXTERNAL |
info | Using external venv | — |
VENV_PYTHON_OK |
info | Python works | — |
VENV_PIP_OK |
info | pip works | — |
POETRY_LOCK_OK |
info | poetry.lock in sync | — |
Symptom: /venv/bin/pip: cannot execute: required file not found
Cause: venv symlinks point to old Python location (e.g., after conda update)
Fix:
python3 xnv.py fix --forceSymptom: POETRY_LOCK_STALE keeps appearing
Cause: pyproject.toml dependencies changed without updating lock
Fix:
python3 xnv.py lock # regenerate lock
python3 xnv.py fix # reinstall with new lockSymptom: CONDA_ACTIVE shows (base) even though you want project venv
Fix:
conda deactivate
python3 xnv.py fix
source venv/bin/activateSymptom: venv/ exists but xnv doesn't detect it
Check: Does venv/pyvenv.cfg exist? If not, it's not a proper venv.
Fix:
python3 xnv.py fix --force┌─────────────────┐ ┌─────────────────┐
│ Standalone │ │ Package │
│ xnv.py │ │ pip install -e │
│ │ │ │
│ • Zero deps │ │ • CLI shortcut │
│ • Copy anywhere│ │ • Importable │
│ • Works when │ │ API │
│ pip broken │ │ │
└─────────────────┘ └─────────────────┘
│ │
└───────────┬───────────┘
│
┌──────▼──────┐
│ Core logic │
│ (diagnose, │
│ fix) │
└─────────────┘
def diagnose(project_dir) -> Diagnosis:
1. Find venv (venv, .venv, env, .env)
2. Check Python binary exists & is executable
3. Check pip binary exists & works
4. Check pyvenv.cfg home dir valid
5. Check poetry.lock sync (if poetry available)
6. Check conda vs venv conflicts
7. Return list of IssuesAdd to your project's Makefile:
# Use standalone xnv.py (no install needed)
fix-env:
@python3 $(XNV_PATH)/xnv.py fix .
doctor-env:
@python3 $(XNV_PATH)/xnv.py doctor .
# Or if xnv installed
fix-env:
@xnv fix .For programmatic use after pip install -e .:
from xnv.diagnose import diagnose, Issue
from xnv.fix import fix
# Diagnose
diag = diagnose("/path/to/project")
print(f"Healthy: {diag.healthy}")
print(f"Venv: {diag.venv_path}")
for issue in diag.issues:
print(f"[{issue.severity}] {issue.code}: {issue.message}")
if issue.fix_hint:
print(f" Hint: {issue.fix_hint}")
# Fix
ok = fix("/path/to/project", force_recreate=False, install=True, dev=False)
if ok:
print("Environment fixed!")
else:
print("Some issues remain")@dataclass
class Issue:
code: str # e.g., "VENV_BROKEN_PYTHON"
severity: str # "error", "warn", "info"
message: str # Human-readable description
fix_hint: str # Suggested fix command
@dataclass
class Diagnosis:
project_dir: Path
venv_path: Path | None
python_path: Path | None
pip_path: Path | None
poetry_available: bool
poetry_lock_stale: bool
conda_active: bool
issues: list[Issue]
@property
def healthy(self) -> bool: ...
@property
def errors(self) -> list[Issue]: ...
@property
def warnings(self) -> list[Issue]: ...xnv.py is a self-contained Python script that:
- Uses only stdlib (
argparse,dataclasses,pathlib,subprocess, etc.) - Implements all diagnosis/fix logic inline
- Has zero external dependencies
- Can be copied to any project and run immediately
This is the bootstrap problem solution: when your package manager (pip/poetry) is broken, you can't use it to install a fix tool. xnv bypasses this by not needing installation.
- Fork and clone
pip install -e ".[dev]"python3 -m pytest tests/ -v- Make changes, add tests
- Submit PR
Apache License 2.0 - see LICENSE for details.
Created by Tom Sapletta - tom@sapletta.com