Pip: `pip install -U` met à niveau les dépendances déjà satisfaites

Créé le 9 juin 2011  ·  23Commentaires  ·  Source: pypa/pip

Si je pip install -U foo , je m'attendrais à ce que la dernière version de foo soit installée, et les dépendances de foo ne seront réinstallées que si elles ne sont pas déjà satisfaites. Mais en fait, les dépendances sont toutes réinstallées même si j'ai déjà des versions identiques installées:


$ pip install -U django-supervisor
Downloading/unpacking django-supervisor
  Downloading django-supervisor-0.2.0.tar.gz
  Running setup.py egg_info for package django-supervisor
Downloading/unpacking supervisor (from django-supervisor)
  Downloading supervisor-3.0a10.tar.gz (438Kb): 438Kb downloaded
  Running setup.py egg_info for package supervisor
    no previously-included directories found matching 'docs/*.pyc'
    no previously-included directories found matching 'docs/.build'
Downloading/unpacking meld3>=0.6.5 (from supervisor->django-supervisor)
  Downloading meld3-0.6.7.tar.gz
  Running setup.py egg_info for package meld3
Installing collected packages: django-supervisor, supervisor, meld3
  Found existing installation: django-supervisor 0.1.1
    Uninstalling django-supervisor:
      Successfully uninstalled django-supervisor
  Running setup.py install for django-supervisor
  Found existing installation: supervisor 3.0a10
    Uninstalling supervisor:
      Successfully uninstalled supervisor
  Running setup.py install for supervisor
    no previously-included directories found matching 'docs/*.pyc'
    no previously-included directories found matching 'docs/.build'
    Skipping installation of /usr/local/ejucovy/django/lib/python2.6/site-packages/supervisor/__init__.py (namespace package)
    Installing /usr/local/ejucovy/django/lib/python2.6/site-packages/supervisor-3.0a10-py2.6-nspkg.pth
    Installing echo_supervisord_conf script to /usr/local/ejucovy/django/bin
    Installing pidproxy script to /usr/local/ejucovy/django/bin
    Installing supervisorctl script to /usr/local/ejucovy/django/bin
    Installing supervisord script to /usr/local/ejucovy/django/bin
  Found existing installation: meld3 0.6.7
    Uninstalling meld3:
      Successfully uninstalled meld3
  Running setup.py install for meld3
Successfully installed django-supervisor supervisor meld3
Cleaning up...

Mes "installations existantes" de supervisor-3.0a10 et meld3-0.6.7 sont toutes deux "désinstallées avec succès", puis des versions identiques sont installées.

upgrade auto-locked bug

Commentaire le plus utile

Je ne pense pas que ce soit un double du # 49. J'ai lu # 49 comme disant que install -U foo ne devrait pas réinstaller _ foo même_ s'il est déjà à la dernière version - ce qui est différent de savoir s'il doit ou non réinstaller foo dépendances déjà satisfaites.

Cette distinction est importante pour les bibliothèques difficiles à construire qui ont des versions fréquentes mais des API assez stables - pour la plupart, une installation suffit - je ne voudrais la réinstaller que si mes dépendances commencent à utiliser de nouvelles fonctionnalités de celles-ci dépendances imbriquées (c'est-à-dire si l'exigence n'est plus satisfaite) - par exemple:

  • foo 0.1 dépend de lxml>=2.3.0
  • foo 0.2 est libéré et dépend de lxml>=2.3.0 (même dépendance)
  • lxml 2.4.0 est libéré

Si j'ai déjà installé foo 0.1 et lxml 2.3.0 , et que je pip install -U foo , je ne voudrais pas qu'il installe lxml 2.4.0 . Il ne devrait installer lxml 2.4.0 lorsque foo commence à dépendre de lxml>=2.4.0 .

Tous les 23 commentaires

À mon avis, c'est un comportement connu, je ne sais pas si c'est vraiment un bogue - je suppose que easy_install a le même comportement.

J'aimerais voir les opinions des autres.

PS: Il y avait une question dans StackOverflow liée à ceci: http://stackoverflow.com/questions/5937756/why-is-pip-looking-for-download-cache-if-the-same-exact-package-is -déjà-installer

Lié au numéro 49

C'est un bug, et c'est un double de # 49.

Je ne pense pas que ce soit un double du # 49. J'ai lu # 49 comme disant que install -U foo ne devrait pas réinstaller _ foo même_ s'il est déjà à la dernière version - ce qui est différent de savoir s'il doit ou non réinstaller foo dépendances déjà satisfaites.

Cette distinction est importante pour les bibliothèques difficiles à construire qui ont des versions fréquentes mais des API assez stables - pour la plupart, une installation suffit - je ne voudrais la réinstaller que si mes dépendances commencent à utiliser de nouvelles fonctionnalités de celles-ci dépendances imbriquées (c'est-à-dire si l'exigence n'est plus satisfaite) - par exemple:

  • foo 0.1 dépend de lxml>=2.3.0
  • foo 0.2 est libéré et dépend de lxml>=2.3.0 (même dépendance)
  • lxml 2.4.0 est libéré

Si j'ai déjà installé foo 0.1 et lxml 2.3.0 , et que je pip install -U foo , je ne voudrais pas qu'il installe lxml 2.4.0 . Il ne devrait installer lxml 2.4.0 lorsque foo commence à dépendre de lxml>=2.4.0 .

Ah, oui, c'est un peu différent. Même si # 49 est corrigé, il y aurait du code supplémentaire nécessaire pour obtenir le comportement souhaité lorsque la dépendance n'est pas dans sa dernière version, mais satisfait toujours les exigences de dépendance.

Je pense que si nous apportions ce changement, certaines personnes trouveraient cela surprenant. Je peux voir pourquoi c'est souhaitable dans certains cas - mais je peux aussi voir des cas où le comportement actuel (moins # 49) est préférable. Donc je suis sur la clôture sur celui-ci.

Une option de ligne de commande supplémentaire serait-elle appropriée? pip install foo --upgrade vs pip install foo --upgrade-recursive ? (Ou --upgrade-nonrecursive si la préservation du comportement actuel de manière rétrocompatible est importante)

rendre les mises à niveau non récursives par défaut assurerait la cohérence avec d'autres gestionnaires de paquets, tels que APT et Portage. et je pense qu'il y a une bonne raison à un tel comportement, c'est qu'il évite les effets secondaires involontaires - si je veux mettre à niveau un package P, alors je voudrais entrer une commande du type upgrade P , pas upgrade P --but-not-other-things .

d'un autre côté, je pense qu'une commande "upgrade all" (voir # 59) devrait être récursive par défaut, puisque "all" devrait vraiment signifier "all" par défaut. dans ce cas, un comportement non récursif signifierait "mettre à jour tous les paquets installés directement, mais pas les dépendances qui n'ont pas été installées directement" (comme le emerge --update @world Portage sans --deep ).

Un problème connexe est que si le package en cours de mise à niveau a une dépendance sur un autre package qui est déjà installé mais non disponible à partir d'un référentiel, Pip échouera et ne pourra pas mettre à niveau le package demandé, bien que ses dépendances soient remplies.

Cela semble se produire aussi bien avec -I qu'avec -U.

Puisque -I signifie --ignore-installed , et est destiné à faire fonctionner pip comme si rien n'était actuellement installé, tout réinstaller est le comportement correct pour -I . Ainsi, le comportement ici n'est qu'un bogue pour -U , pas pour -I .

easy_install n'a pas le même comportement. easy_install ne réinstallera pas les dépendances si elles sont déjà remplies.

ce n'est pas une fonctionnalité ou un comportement, c'est un bogue.

c'est aussi très ennuyeux - tester la distribution PIP pour le package d'un framework, ou mettre à jour un seul module complémentaire de framework, signifie avoir besoin de réinstaller l'ensemble du framework et toutes ses dépendances. ces téléchargements et installations inutiles sont une perte de temps et de ressources.

pour ceux qui veulent juste un moyen de le faire _ maintenant_, à moins qu'un comportement / code change en "-U"

Je pense que cela permet d'obtenir le résultat souhaité, non?

mettre à niveau les exigences de niveau supérieur uniquement:

  • pip install -U --no-deps REQS // met à niveau uniquement le niveau supérieur
  • pip install REQS // ce 2ème passage installera toutes les _nouvelles_ dépendances de la mise à niveau

Pour le cas le plus simple, cela suffit, mais je ne pense pas que cela fonctionne pour un fichier requirements.txt, ou s'il existe des dépendances qui ont des mises à jour de leurs install_requires. Nous avons un script compliqué qui fait une différence de notre requirements.txt et fait plus ou moins ce que vous décrivez, mais il ne gère pas la profondeur de mise à niveau> 1.

Ce qui complique les choses dans une certaine mesure, c'est que de nombreux paquets django commentent ou suppriment leurs lignes install_requires à cause de ce bogue; sinon, ils se retrouvent avec une version alpha de django installée (cela a été notre expérience, et je l'ai vu dans les problèmes github de nombreux paquets django importants.

Hey @fdintino , j'ai monté un test de base avec les exigences, -U et --no-deps et cela a semblé fonctionner, c'est-à-dire que les éléments du fichier des exigences ont été mis à jour, mais pas de dépendances. cela correspond à ma compréhension de ce que fait le code. c'est fastidieux là-dedans cependant, donc il pourrait y avoir un échec avec cette idée.

pour le cas où une exigence de niveau supérieur a une nouvelle dépendance "install_requires", c'est pourquoi j'ai mentionné la commande 2nd pass pour les installer.

pour le cas où il y a "des dépendances qui ont des mises à jour de leurs install_requires", je ne suis pas sûr de vous y suivre. vous ne découvririez et voudriez agir que si vous vouliez faire une mise à niveau récursive complète, non?

Seulement si vous ne remplissez plus les conditions. Ainsi, par exemple, si j'ai mis à jour django-sentry, et que django-sentry nécessitait django-celery>=2.5.4,django-celery<3.0 là où il nécessitait auparavant django-celery>=2.5.3,django-celery<3.0 (peut-être à cause d'une correction de bogue ou d'une nouvelle fonctionnalité), et j'ai django-celery==2.5.3 , alors je m'attendrais à ce qu'il mette à jour django-celery pour satisfaire l'exigence, comme le fait mon patch. Cependant, si j'avais django-celery==2.5.4 je ne m'attendrais pas à ce qu'il mette à jour le céleri. Dans le cas du céleri, ce n'est pas un gros problème, mais lorsque les paquets ont Django>1.2,Django<=1.4 et que les projets sont souvent écrits pour cibler Django 1.2, 1.3 ou 1.4, une mise à jour inattendue de django peut être un énorme casse-tête.

merci @fdintino . Je suis maintenant. vous ne voulez pas couper tous les comportements récursifs (qui feront les mises à jour nécessaires pour répondre aux exigences), vous voulez juste arrêter les mises à jour "forcées" récursives.

btw, votre commentaire est rogné en raison du formatage. voudra peut-être résoudre ce problème pour d'autres.

J'ai posté un résumé qui décrit la réalisation du comportement souhaité en utilisant les 2 commandes dans l'ordre mentionné ci-dessus.
Non pas que cela invalide le désir pour ce billet ou le pull, mais cela m'a été utile de confirmer comment
cela fonctionne actuellement et ce qui est possible actuellement.
(indice: dans l'exemple, "b" est le parallèle à django qui a été mentionné comme un problème)

https://gist.github.com/3088149

commentaire apprécié sur l'essentiel si ce n'est pas le scénario.

Je remarque que cela est ouvert depuis longtemps.

J'ai trouvé que ma version de pip a maintenant la possibilité de faire

pip install --upgrade --upgrade-strategy=only-if-needed package

Cela semble être le comportement souhaité, bien que plutôt verbeux. Personnellement, je pense que cela aurait été génial si c'était la valeur par défaut, mais il est peut-être trop tard pour changer maintenant.

S'il est trop tard pour modifier la valeur par défaut, je pense que cela peut être fermé?

Dans https://github.com/pypa/pip/issues/3871#issuecomment -247789343, j'ai mentionné ce que je pense être la façon dont nous allons avancer sur ce point, en reproduisant ici:

Revenons à ceci maintenant. Voici ce que je pense que nous devrions faire:

  1. Ajoutez --upgrade-strategy = [désireux / non désireux] dans pip vX qui vaut par défaut eager , et autorisez les gens à adhérer à la stratégie non désireuse. Cela nous permettra d'obtenir des tests dans le monde réel de la part de personnes sans forcer tout le monde à changer à la fois.
  2. Une fois que nous avons traité les commentaires de 1., changez la valeur par défaut de --upgrade-strategy en non-eager dans pip vX + 1. Cela nous permettra une grande utilisation dans le monde réel en imposant un changement à tout le monde, mais donne une trappe de secours aux personnes qui, pour une raison quelconque, sont brisées par le changement.
  3. Une fois que nous avons traité les commentaires de 2., regardez comment déprécier --upgrade-strategy dans pip vx + 2 (à supprimer conformément à notre politique de dépréciation normale).

Cela aura un délai plus long avant que le non-désireux soit la valeur par défaut, mais cela nous permet de le mettre en phase plus lentement pour nous assurer qu'il n'y a pas de cas d'utilisation qui va en déranger. Idéalement, je pense que nous voudrions éventuellement nous débarrasser de l'indicateur --upgrade-strategy . Ce type d'indicateur donne l'impression de ne demander que des problèmes de rupture, car il nous oblige essentiellement à dupliquer nos tests de mise à niveau pour tester complètement les choses. Je pense que c'est un bon indicateur à ajouter pour le moment, pour permettre la mise en place progressive et faire face à toute rupture.

D'accord, ça sonne bien, j'attendrai la fin de l'étape 2. Semble que l'autre problème est un doublon, mais déjà fermé.

@xavfernandez @dstufft Est-ce que cela peut être fermé ou allons-nous attendre que les commutateurs par défaut?

Nous attendrons probablement les commutateurs par défaut.

Clôture, depuis la fusion du n ° 4500

Cette page vous a été utile?
0 / 5 - 0 notes