~/wiki

Cheatsheets — vue longue

retour à la liste

Toutes les pages concaténées sur un seul document, pour un Ctrl-F direct.

Gère des versions de Python, pas des paquets. Fonctionne par shims : de faux exécutables placés très tôt dans le PATH, qui redirigent vers la version active.

Voir et installer

pyenv versions        # installées, l'active marquée d'une étoile
pyenv version         # l'active ICI, et qui l'a décidée
pyenv install --list | rg "^\s*3\.12"
pyenv install 3.12.9
pyenv version
3.12.9 (set by /Users/edouard/code/mon-projet/.python-version)

La deuxième partie est la plus utile : elle dit quel fichier impose la version.

Choisir une version

pyenv global 3.12.9      # défaut de la machine  -> ~/.pyenv/version
pyenv local 3.12.9       # ce dossier            -> ./.python-version
pyenv shell 3.12.9       # ce shell seulement    -> $PYENV_VERSION
pyenv local --unset

Ordre de priorité : shell > local > global.

Environnements nommés (plugin pyenv-virtualenv)

pyenv virtualenv 3.12.9 mon-env    # -> ~/.pyenv/versions/3.12.9/envs/mon-env
pyenv local mon-env                # activation automatique en entrant dans le dossier
pyenv activate mon-env
pyenv deactivate
pyenv virtualenv-delete mon-env

Ils vivent dans ~/.pyenv/versions/, pas dans le projet. C'est la différence de fond avec un .venv local.

venv standard, sans le plugin

pyenv local 3.12.9
python -m venv .venv
source .venv/bin/activate
pip install httpx pydantic
pip freeze > requirements.txt
deactivate

Les deux pièges qui coûtent des minutes

Le shim répond à la place du venv. Un paquet installé dans le venv, et pourtant la commande résolue est celle de pyenv :

which uvicorn
/Users/edouard/.pyenv/versions/lewagon/bin/uvicorn

Contournement immédiat : python -m uvicorn main:app passe par le Python courant et ignore le PATH. Sinon hash -r (zsh : rehash) vide le cache de commandes du shell.

La commande existe ailleurs. Message classique :

pyenv: jupyter: command not found

The `jupyter' command exists in these Python versions:
  3.12.9/envs/lewagon
  3.10.6/envs/taxifare-env

Le shim cherche dans la version active, qui n'a pas le paquet. Soit on active le bon environnement, soit on passe par uv run.

Diagnostic

which -a python python3     # tous les candidats, dans l'ordre du PATH
pyenv which python          # ce que pyenv résoudrait
pyenv doctor                # si le plugin est installé
PYENV_VERSION=system python -V   # contournement ponctuel

Rapport avec uv

uv est indépendant : il télécharge ses propres interpréteurs dans ~/.local/share/uv/python/ et ne consulte jamais pyenv. Seul point de friction : les deux lisent .python-version.

See also

Gestionnaire de projets Python en Rust. Remplace pyenv + venv + pip + pip-tools d'un seul coup, et télécharge ses propres interpréteurs.

Démarrer un projet

uv init --python 3.12 mon-projet
cd mon-projet
uv add httpx pydantic pytest
uv run python -V
Using CPython 3.12.11
Creating virtual environment at: .venv
Python 3.12.11

Toujours passer --python. Sans lui, uv prend sa version par défaut — souvent une 3.13 ou 3.14 — et écrit requires-python = ">=3.13" dans le pyproject.toml.

uv init crée pyproject.toml, .python-version, main.py, README.md, .gitignore et un dépôt git. Le .venv/ n'apparaît qu'au premier add ou run.

Variante Résultat
uv init projet application, fichiers à plat
uv init --package src/<nom>/__init__.py + [build-system]
uv init --lib idem plus py.typed

Le quotidien

uv add httpx                  # ajoute et installe
uv add --dev pytest ruff      # dépendance de dev
uv remove httpx
uv sync                       # aligne .venv sur uv.lock
uv lock                       # regénère le lock sans installer
uv tree                       # arbre des dépendances
uv run <commande>             # exécute dans le venv, sans activation

uv add et uv run synchronisent implicitement. uv sync sert surtout après un clone, ou quand le .venv est cassé.

uv sync désinstalle ce qui n'est pas dans le lock, contrairement à pip install -r.

uv sync
Resolved 100 packages in 4ms
Uninstalled 3 packages in 8ms
 - markdown-it-py==4.2.0
 - mdurl==0.1.2
 - rich==15.0.0

Reprendre un repo existant

git clone <url> && cd <repo> && ls
Ce qu'on trouve Ce qu'on lance
uv.lock uv sync
pyproject.toml seul uv sync (le lock est généré)
requirements.txt uv venv --python 3.12 puis uv pip install -r requirements.txt
poetry.lock poetry install, ou uv pip install -e .
rien uv init --python 3.12

uv venv + uv pip ne modifient aucun fichier du repo — c'est la voie propre pour accélérer l'installation chez un client sans imposer son outillage.

Le piège .python-version

uv et pyenv lisent ce fichier. Si uv y écrit 3.13 et que pyenv n'a pas de 3.13, pyenv affiche une erreur à chaque commande dans ce dossier. C'est du bruit, uv continue de fonctionner, mais c'est pénible.

# corriger requires-python dans pyproject.toml D'ABORD
uv python pin 3.12
Updated `.python-version` from `3.13` -> `3.12`

Dans l'autre ordre, uv refuse : The requested Python version 3.12 is incompatible with the project requires-python value of >=3.13.

Outils globaux

uv tool install ruff          # installé isolément, disponible partout
uv tool list
uvx ruff check .              # exécute sans installer

Diagnostic

uv run python -c "import sys; print(sys.executable)"
/Users/edouard/code/mon-projet/.venv/bin/python3

Le chemin doit contenir /.venv/ et être dans le projet. S'il pointe vers .pyenv/shims, /opt/homebrew ou /usr/bin, on n'est pas où on croit.

uv python list        # interpréteurs connus
uv cache clean        # vider le cache

Pour un live coding sous pression, activer une fois et oublier le préfixe :

source .venv/bin/activate

See also