Comment puis-je utiliser un fichier d'exigences pip pour désinstaller et installer des packages?

90

J'ai un fichier d'exigences pip qui change pendant le développement.

Peut- pipon désinstaller les packages qui n'apparaissent pas dans le fichier des exigences et installer ceux qui apparaissent? Existe-t-il une méthode standard?

Cela permettrait au fichier d'exigences pip d'être la liste canonique des paquets - une approche «si et seulement si».

Mise à jour : je l'ai suggéré comme nouvelle fonctionnalité sur https://github.com/pypa/pip/issues/716

wodow
la source
3
Voulez-vous VRAIMENT que pip désinstalle des paquets arbitraires simplement parce que votre programme n'en a pas besoin? Cela semble juste un peu dangereux ...
Scott Hunter
11
@ScottHunter Si vous êtes dans une virtualenv sans packages de site, c'est une chose raisonnable à faire.
Michael Mior
1
@ScottHunter Oui si vous utilisez un environnement contrôlé (virtuel) où je veux être certain de ce qu'il y a - et il n'y a rien d'autre qui pourrait éventuellement causer des problèmes, par exemple des dépendances inattendues.
wodow
@MichaelMior Si c'est la réponse, veuillez l'ajouter comme réponse et je l'accepterai!
wodow
@wodow terminé. La seule raison pour laquelle je n'ai pas publié de réponse est qu'il existe probablement une solution plus utile qui peut vous amener à ce que vous voulez.
Michael Mior

Réponses:

16

La réponse courte est non, vous ne pouvez pas faire cela avec pip.

Michael Mior
la source
32
comme Stephen le dit ci-dessous:pip uninstall -r requirements.txt
Ommit
31
@Ommit Cela ne désinstalle pas les packages qui n'apparaissent pas dans le fichier des exigences. Il désinstalle tous les packages qui apparaissent dans le fichier.
Michael Mior
3
@Micheal Mior, euh, je n'ai pas prêté suffisamment attention à la question initiale. Ma faute.
Ommit
4
Ajoutez une commande -yà @Ommit pour éviter d'avoir à appuyer sur Y et à saisir plusieurs fois. Apprenez de mes erreurs.
Greg Hilston
1
Juste pour ajouter: pip uninstall -r requirements.txtne désinstallera que les versions de votre requirements.txt. Si vous désinstallez boto3==1.10.0par exemple, pip freezes'affiche boto3==1.0.1si vous l'avez déjà installé (ou une version plus ancienne).
Jordan Mackie
125

Cela devrait désinstaller tout ce qui ne figure pas dans requirements.txt:

pip freeze | grep -v -f requirements.txt - | grep -v '^#' | xargs pip uninstall -y

Bien que cela ne fonctionne pas tout à fait correctement avec les paquets installés avec -e, c'est-à-dire à partir d'un dépôt git ou similaire. Pour les ignorer, il suffit de filtrer les paquets commençant par l' -eindicateur:

pip freeze | grep -v -f requirements.txt - | grep -v '^#' | grep -v '^-e ' | xargs pip uninstall -y

Ensuite, évidemment:

pip install -r requirements.txt

Mise à jour pour 2016: vous ne voulez probablement pas vraiment utiliser l'approche ci-dessus, cependant. Découvrez pip-toolsetpip-sync qui accomplissent ce que vous cherchez probablement à faire d'une manière beaucoup plus robuste.

https://github.com/nvie/pip-tools

Mise à jour pour mai 2016:

Vous pouvez maintenant également utiliser pip uninstall -r requirements.txt, mais cela accomplit fondamentalement le contraire - il désinstalle tout dansrequirements.txt

Mise à jour pour mai 2019:

Découvrez pipenv . Beaucoup de choses se sont passées dans le monde de la gestion des paquets qui rendent ce genre de question un peu obsolète. En fait, j'utilise toujours avec plaisir les outils pip.

Stephen Fuhry
la source
5
Ce serait bien. Cela me semble être un bon moyen de forcer les développeurs à être explicites sur leurs dépendances en cassant tout s'ils installent quelque chose sur un hôte manuellement sans mettre à jour leurs requirements.txt. Je serais intéressé de voir quel genre de commentaires une demande d'extraction ajoutant cette fonctionnalité générerait.
Stephen Fuhry
C'est la bonne réponse! Je mets cela dans mon project.configfichier pour Django sur Elastic Beanstalk: 05_pip_clean: command: "pip freeze | grep -v -f requirements.txt - | grep -v '^#' | xargs pip uninstall -y". Maintenant, je peux restaurer les packages pip sans reconstruire mon environnement simplement en utilisant des commentaires dans requirements.txt. Cela me fait gagner un temps d'arrêt réel. Merci!
e.thompsy
y a-t-il déjà une sortie de pip freeze commençant par #? En d'autres termes, le second grep est-il nécessaire?
xor
1
Je ne sais pas si pip freezefait des commentaires, mais un jour, ils peuvent l'ajouter à l'API, et s'ils le font, ce sera valide. S'ils ne le font pas, alors ce qui précède est interdit. Le tiret vous permet d'utiliser stdin de la commande précédente, dans ce cas, le tiret indique à grep de comparer le contenu de requirements.txt à la sortie de pip freeze(la sortie de pip freezedans ce contexte est synonyme de stdin)
Stephen Fuhry
1
J'ai fortement recommandé pip-tools. +1
ron rothman
16

Ce n'est pas une caractéristique de pip, non. Si vous voulez vraiment une telle chose, vous pouvez écrire un script pour comparer la sortie pip freezeavec le vôtre requirements.txt, mais ce serait probablement plus compliqué que cela ne vaut la peine.

En utilisant virtualenv, il est plus facile et plus fiable de créer simplement un environnement propre et de (ré) installer à partir de requirements.txt, comme:

deactivate
rm -rf venv/
virtualenv venv/
source venv/bin/activate
pip install -r requirements.txt
dbr
la source
6
Il peut être utile de simplement désinstaller les packages qui ne sont pas dans le fichier des exigences si certains des packages (PIL, lxml, etc.) nécessitent une longue compilation - en particulier si cela se déroule sur un serveur en direct qui utilise l'environnement virtuel.
melinath
@melinath S'ils ne sont pas dans votre fichier d'exigences et qu'ils sont déjà installés, la compilation ne devrait plus jamais avoir à se produire.
Michael Mior
1
@MichaelMior - à moins que vous ne deviez, par exemple, effacer tout le virtualenv, comme le suggère cette réponse.
melinath
1
@melinath Mais si vous effacez le virtualenv et que le paquet n'est pas requis (et pas dans votre requirements.txt), pourquoi serait-il jamais réinstallé ?
Michael Mior
3
@MichaelMior Je vais essayer de dire mon commentaire original plus explicitement. Il semble que vous ayez mal compris ce que je voulais dire. Imaginez un simple fichier d'exigences contenant PIL et lxml. Mais alors vous décidez que vous n'avez plus besoin de lxml, et vous le supprimez du fichier des exigences. Si vous faites ce que suggère cette réponse et effacez le virtualenv, vous devez alors réinstaller (et recompiler) PIL. Il serait plus efficace d'avoir la possibilité de simplement désinstaller lxml (c'est-à-dire tous les paquets ne figurant pas dans le fichier des exigences.)
melinath
11

Vous pouvez maintenant passer l' -r requirements.txtargument à pip uninstall.

pip uninstall -r requirements.txt -y

Au moins à partir de pip8.1.2, pip help uninstallmontre:

...
Uninstall Options:
  -r, --requirement <file>    Uninstall all the packages listed in the given requirements file.  This option can be
                              used multiple times.
...
Shinto Joseph
la source
3
Cela ne désinstalle pas les packages qui n'apparaissent pas dans le fichier. Il désinstalle les paquets qui n'apparaissent dans le fichier.
Michael Mior
4

C'est une vieille question (mais bonne), et les choses ont considérablement changé depuis qu'elle a été posée.

Il y a une référence désinvolte à pip-syncune autre réponse, mais mérite sa propre réponse, car elle résout précisément le problème du PO.

pip-sync prend un requirements.txtfichier comme entrée, et «vérifie» votre environnement Python actuel afin qu'il corresponde exactement à ce qu'il contient requirements.txt. Cela inclut la suppression de tous les packages présents dans votre env mais absents de requirements.txt.

Exemple: Supposons que nous voulons que notre env contienne (seulement) 3: bibliothèques libA, libBet libC, comme ceci:

> cat requirements.txt
libA==1.0
libB==1.1
libC==1.2

Mais notre env contient actuellement libCet libD:

> pip freeze
libC==1.2
libD==1.3

L'exécution de pip-sync entraînera ceci, qui était notre état final souhaité:

> pip-sync requirements.txt
> pip freeze
libA==1.0
libB==1.1
libC==1.2
Ron Rothman
la source
attention, si vous avez un pip-tools installé globalement, il ne se désinstallera pas dans votre virtualenv actuellement activé ... encore étrange, mais sinon l'outil de gestion des exigences le plus simple que je connaisse.
benzkji
3

La proposition de Stephen est une bonne idée, mais malheureusement cela ne fonctionne pas si vous n'incluez que des exigences directes dans votre fichier, ce qui me semble plus clair.

Toutes les dépendances seront désinstallées, y compris même distribute, se décomposant pip.

Maintenir un fichier d'exigences propre tout en suivant la version d'un environnement virtuel

Voici comment j'essaie de suivre les versions de mon environnement virtuel. J'essaie de maintenir un minimum requirements.txt, en incluant uniquement les exigences directes, et en ne mentionnant même pas les contraintes de version là où je ne suis pas sûr.

Mais en plus, je garde, et j'inclus dans le suivi de version (disons git), le statut réel de mon virtualenv dans un venv.pipfichier.

Voici un exemple de workflow:


configuration de l'espace de travail virtualenv, avec suivi des versions:

mkdir /tmp/pip_uninstalling
cd /tmp/pip_uninstalling
virtualenv venv
. venv/bin/activate

initialiser le système de suivi de version:

git init
echo venv > .gitignore
pip freeze > venv.pip
git add .gitignore venv.pip
git commit -m "Python project with venv"

installez un package avec des dépendances, incluez-le dans le fichier des exigences:

echo flask > requirements.txt
pip install -r requirements.txt
pip freeze > venv.pip

Maintenant, commencez à créer votre application, puis validez et démarrez une nouvelle branche:

vim myapp.py
git commit -am "Simple flask application"
git checkout -b "experiments"

installez un package supplémentaire:

echo flask-script >> requirements.txt
pip install -r requirements.txt
pip freeze > venv.pip

... jouez avec, puis revenez à la version précédente

vim manage.py
git commit -am "Playing with flask-script"
git checkout master

Désinstallez maintenant les packages superflus:

pip freeze | grep -v -f venv.pip | xargs pip uninstall -y

Je suppose que le processus peut être automatisé avec des hooks git, mais ne sortons pas du sujet.

Bien sûr, il est logique d'utiliser un système de mise en cache de paquets ou un référentiel local comme pip2pi

Chemin rocailleux
la source
2

Piggybacking off @ stephen-j-fuhry voici un équivalent PowerShell que j'utilise:

pip freeze | ? { $_ -notmatch ((gc req.txt) -join "|") }
par exemple beurre
la source
0

Bien que cela ne réponde pas directement à la question, une meilleure alternative à requirements.txtmaintenant consiste à utiliser un Pipfile. Cela fonctionne de la même manière qu'un Ruby Gemfile. Actuellement, vous devez utiliser l' pipenvoutil, mais j'espère que cela sera éventuellement intégré à pip. Cela fournit la pipenv cleancommande qui fait ce que vous voulez.

(Notez que vous pouvez importer un existant requirements.txtavec pipenv install -r requirements.txt. Après cela, vous devriez avoir un Pipfileet le requirements.txtpeut être supprimé.)

Michael Mior
la source
-3

Il est désormais possible d'utiliser:

pip uninstall -r requirements.txt
Roberto Nunes
la source
2
Cela ne désinstalle pas les packages qui n'apparaissent pas dans le fichier des exigences. Il désinstalle tous les paquets qui n'apparaissent dans le fichier.
Michael Mior