Pipenv: [question] Comment intégrer setup.py ?

Créé le 7 févr. 2017  ·  38Commentaires  ·  Source: pypa/pipenv

En utilisant requirements.txt , je peux le faire :

from pip.req import parse_requirements
requirements = [str(r.req) for r in
                parse_requirements('requirements.txt', session=False)]
test_requirements = [str(r.req) for r in
                     parse_requirements('requirements-test.txt', session=False)]

Comment puis-je faire la même chose en utilisant Pipfile ?

Commentaire le plus utile

Tout d'abord, avis de non-responsabilité : mon expertise concerne principalement les packages lib. Je risque de rater certains points. J'ai le droit d'avoir tort, et je suis prêt à l'utiliser !
De plus, cela m'a fait me gratter la tête à quelques reprises. J'aimerais vraiment avoir un avis là-dessus.

Maintenant, venons-en à ça.

Je vais commencer par cette déclaration @elgertam :

[...] mon utilisation de Pipfile me fait penser que install_requires est vraiment presque identique à ce qui se passe dans le Pipfile. Si j'ai besoin de numpy, j'installe pipenv numpy et une nouvelle entrée entre dans le groupe [packages] de mon Pipfile [...]

Vous avez ajouté numpy à votre environnement, vous n'avez pas ajouté numpy aux dépendances de votre application.
Ce sont deux choses différentes. Continuez à lire, vous verrez ce que je veux dire.

En d'autres termes, mon utilisation est totalement différente de requirements.txt, que j'avais l'habitude de générer avant de valider en utilisant pip freeze > requirements.txt.

Étonnamment, votre utilisation n'est pas si différente si vous y réfléchissez :

  • Votre flux de travail précédent : pip install stuff -> pip freeze > requirements.txt -> flux install_requires partir de requirements.txt
  • Votre nouveau flux de travail (tenté) : pipenv install stuff -> Pipfile automatiquement mis à jour -> essaie d'alimenter install_requires avec le Pipfile .
  • Quelle est l'idée prévue : ajoutez des éléments à install_requires -> pipenv install -> Environnement et Pipfile.lock sont mis à jour.

Et pour cette façon de travailler, vous voulez un Pipfile qui indique que vous voulez installer votre application.
Quelque chose comme le requests Pipfile lié par @isobit.

Ou, un exemple :

[[source]]
url = "https://pypi.python.org/simple"
verify_ssl = true

[dev-packages]
pytest = ">=2.8.0"
tox = "*"

[packages]
"-e ." = "*"

Votre Pipfile sert à décrire votre environnement, pas les dépendances d'un paquet. Comme vous le voyez, le Pipfile ci-dessus définit ce que je veux installer, qui est le package local en mode modifiable.

Cela peut sembler un peu "inutile", car pour le moment tout est piloté par un seul paquet, mais disons que vous voulez installer votre application, mais avec requests[security] , mais ce n'est pas une dépendance stricte de votre application, vous faites pipenv install requests[security] , puis :

[[source]]
url = "https://pypi.python.org/simple"
verify_ssl = true

[dev-packages]
pytest = ">=2.8.0"
tox = "*"

[packages]
"-e ." = "*"
requests = { extras = ['security'] }

Et voilà, voici un exemple de la différence entre vos exigences abstraites et vos exigences concrètes. Il en va de même si vous vouliez installer gunicorn ou tout autre élément nécessaire dans l'environnement, mais cela ne fait pas partie de l'application elle-même.

Qu'est-ce qui me manque ici, @vphilippon ? Pourquoi les [packages] de Pipfile sont-ils trop limités pour être utilisés dans install_requires ou tests_require ?

Si je l'ai assez bien expliqué, vous pouvez voir que c'est juste censé être l'inverse.
Vous mettez vos dépendances dans install_requires , vous mettez votre package dans le Pipfile , puis vous obtenez un environnement, avec un Pipfile.lock pour la reproductibilité (car il résoudra et respectera votre dépendances du paquet).

Pour test_require , j'avoue que je ne suis pas sûr que ça rentre dans tout ça. IIRC, c'est une caractéristique spécifique setuptools . Nous pourrions dire qu'il s'agit d'un ensemble de dépendances abstraites pour les tests, et nous attendre à ce que pipenv résolve et installe celles qui font ensuite pipenv install --dev , pour tous les packages, mais j'ai l'impression que ce n'est pas tout à fait correct. Je n'ai pas d'idée ou d'opinion claire à ce sujet et sur la justification qui l'entoure, désolé.

J'espère que tout cela a du sens d'une manière ou d'une autre.

Tous les 38 commentaires

Vous devriez pouvoir accomplir cela avec le code ci-dessous. Cela chargera le Pipfile de votre projet actuel et renverra les dépendances dans une liste compatible pip.

from pipenv.project import Project
from pipenv.utils import convert_deps_to_pip

pfile = Project(chdir=False).parsed_pipfile
requirements = convert_deps_to_pip(pfile['packages'], r=False)
test_requirements = convert_deps_to_pip(pfile['dev-packages'], r=False)

Faites-nous savoir si vous avez d'autres questions :)

Ce qui précède est très utile. J'ai rencontré des problèmes avec setup.py en fonction de l'installation de Pipenv dans un virtualenv avant que setup.py install (ou toute autre chose) puisse être exécuté. Les seules solutions à ce problème auxquelles je peux penser sont soit de vendre Pipenv dans un projet, ce qui semble loin d'être idéal, soit même de pirater le fichier setup.py pour installer Pipenv avant d'essayer d'exécuter les importations from pipenv... , ce qui semble tort. Quelqu'un a-t-il des idées ou de meilleures solutions que celle-ci?

Devrions-nous ~harceler~ suggérer aux autres membres de la communauté Python (PyPA, etc.) de simplement bénir Pipenv en tant qu'outil officiellement inclus dans les futures versions de Python ? 😄

Serait-il utile d'ajouter pipenv à setup_requires ? Il semble qu'il pourrait également être nécessaire de l'ajouter à install_requires , ce qui semble malheureux.

Ne faites pas cela.

@kennethreitz que voulez-vous dire par "ceci" ? Voulez-vous dire l'intégration avec setup.py, la solution @nateprewitt ou les deux dernières suggestions ?

Alors, comment les utilisateurs doivent-ils savoir qu'ils ont besoin d'installer pipenv ?

Étant donné que pipenv est un outil utilisé pour installer des choses, et non l'inverse, il n'y a aucune raison de l'exiger dans votre setup.py. La chose contre laquelle Kenneth met en garde est l'importation de pipenv dans setup.py car il s'agit d'une application cli et peut causer des problèmes.

Le 17 octobre 2017, à 9h37, Iddan Ahahronson [email protected] a écrit :

Alors, comment les utilisateurs doivent-ils savoir qu'ils ont besoin d'installer pipenv ?


Vous recevez ceci parce que vous êtes abonné à ce fil.
Répondez directement à cet e-mail, consultez-le sur GitHub ou désactivez le fil de discussion.

alors comment puis-je utiliser le code de @nateprewitt - dans setup.py ?

@iddan : J'ai tenté de résoudre le problème d'amorçage de Pipenv en vendant simplement une version de Pipenv dans le squelette de mon projet (https://github.com/elgertam/cookiecutter-pypackage/blob/master/%7B%7Bcookiecutter.project_slug%7D %7D/setup.py). Jusqu'à présent, je n'ai eu aucun problème, même si je ne peux pas dire que j'ai eu beaucoup d'occasions de le tester dans une situation où j'installe un paquet en utilisant setup.py .

Je peux comprendre pourquoi nous serions inquiets de ne pas exécuter de CLI lors du chargement de setup.py, mais d'après ce que je peux dire, le code que j'utilise (copier-coller du post de @nateprewitt ici) est assez sûr.

Je pense que ce hack ne sera plus nécessaire lorsque pip aura suffisamment d'éléments internes pour comprendre le format Pipfile.

@iddan , pour être clair, ce code sert uniquement à convertir les dépendances de Pipfiles dans un format de style requirements.txt que pip lira. Il semble que Kenneth ait rédigé quelque chose du message original, mais je ne sais pas quoi.

Pipenv est conçu comme un outil de gestion et de déploiement d'environnement, et non pour une distribution comme setup.py. Nous vous suggérons fortement de documenter que vous utilisez un Pipfile et éventuellement de créer un lien vers pipenv.org pour les instructions d'installation. Traitez cela de la même manière que vous traitez pip, on ne s'attend pas à ce qu'un utilisateur installe pip chaque fois qu'il installe un nouveau package Python.

Je comprends parfaitement cela. Ce que je ne comprends pas, c'est à quoi vous attendez-vous lorsqu'un utilisateur télécharge un package à l'aide de ce script et que pipenv n'est pas installé

@nateprewitt , si nous voulons distribuer un paquet alors (par les moyens habituels, en utilisant pip ), devrions-nous conserver une copie de la liste de dépendances dans setup.py ou un requirements.txt ? J'espérais utiliser mon Pipfile comme source unique de vérité.

Pour clarifier, je suppose que le code de la première réponse est destiné à être exécuté dans le cadre d'une construction, plutôt que d'être réellement utilisé dans un setup.py .

Sauf erreur de ma part, le code dans https://github.com/kennethreitz/pipenv/issues/209#issuecomment -278185133 peut être utilisé en toute sécurité si vous construisez une roue (=dist binaire), mais pas si vous construisez sdist (=dist source).

Pour les roues, setup.py n'est pas inclus dans le package (mais est plutôt évalué au moment de la construction, et les fichiers de métadonnées sont construits en fonction des informations qu'il recueille). Avec wheels, setup.py n'est jamais exécuté sur la machine où le paquet est installé, seulement là où il a été construit.

Avec sdist, setup.py est en fait exécuté sur la machine d'installation et donc pipenv doit y être disponible.

Oh oui. @tuukkamustonen , mon cas d'utilisation particulier est un sdist. Comme je ne veux pas obliger l'utilisateur du package à installer pipenv avant de faire un pip install , je suppose que je suis coincé avec la dérivation de mon install_requires en dehors de setup.py (c'est-à-dire manuellement ou dans le cadre d'un build) ?

Si je lis correctement, je crois que Kenneth et les autres responsables ne veulent pas que nous traitions Pipenv comme une dépendance de projet comme nous le ferions pour pytest , ou même une dépendance de paquet normale. Idéalement, il semble que nous devrions installer et mettre à jour Pipenv de la même manière que pip lui-même, c'est-à-dire pip est installé lorsque Python est installé ou lorsqu'un virtualenv est créé. C'est ce que voulait dire Kenneth lorsqu'il a dit : « Ne fais pas ça.

Cela dit, @isobit a fait écho à mes pensées selon lesquelles Pipfile devrait être la seule source de vérité. Je peux voir deux cas d'utilisation convaincants pour favoriser Pipfile (et il y en a d'autres) : premièrement, un pipeline CI/CD qui dépend de Pipfile pour configurer l'environnement de construction est beaucoup plus robuste qu'un pipeline dépendant de requirements.txt ; et deuxièmement, un contributeur peut essayer aveuglément d'installer un projet basé sur Pipfile peut être frustré si python setup.py install ne fonctionne pas comme prévu. Considérant que ni Pipenv ni le pip compatible avec Pipfile ne sont encore des outils Python standard, et que Pipenv est en effet l'implémentation de référence pour Pipfile, nous avons peu d'options pour résoudre le problème :

1) Précisez dans la documentation de votre projet que votre projet dépend de Pipenv . Vous pouvez toujours compter sur Pipenv dans votre setup.py , et cela s'arrêtera si Pipenv n'est pas installé dans votre environnement Python. Concrètement, un contributeur à votre code devrait installer manuellement Pipenv sur son virtualenv afin d'installer le projet avec setup.py .
2) Toujours faire dépendre setup.py de requirements.txt , que vous générez périodiquement en fonction de votre Pipfile . Cela reste entièrement compatible avec pip et setuptools , mais nécessite que tout responsable génère le requirements.txt chaque fois que le projet est construit et déployé. Une variante possible serait qu'un pipeline CI/CD mette à jour les requirements.txt au moment de la construction.
3) Vendoriser une version de Pipenv dans un projet et l'appeler en utilisant from _vendor.pipenv.project import Project... à l'intérieur setup.py . Une variante de ceci pourrait être de n'importer qu'à partir de la version fournisseur lorsque l'importation globale échoue.
4) Une autre option qui n'est pas présentée ici et à laquelle je ne suis pas assez intelligent pour penser.

J'utilise personnellement (3) (voir https://github.com/kennethreitz/pipenv/issues/209#issuecomment-300550425) jusqu'à ce que Pipfile devienne plus un standard commun, auquel cas je n'aurai plus aucun de mes projets dépendent directement du code Pipenv, puisque Pipenv semble clairement destiné à être un outil de gestion d'un virtualenv basé sur un Pipfile, et pas nécessairement une bibliothèque Pipfile elle-même.

J'espère que cela clarifie le problème sur la base de ce que j'ai lu ici, mais si je me suis mal exprimé ou ai dit quelque chose de flagrant, faites-le moi savoir @nateprewitt.

J'ai le sentiment que le problème ici provient d'une mauvaise utilisation originale (IMO) du requirements.txt pour commencer. C'est en dehors de l'utilisation de pipenv .

Je vais pointer vers ce merveilleux article de Donald Stufft, setup.py vs requirements.txt :
https://caremad.io/posts/2013/07/setup-vs-requirement/

TL;DR (mais vous devriez vraiment lire cependant) : Le setup.py install_requires est destiné à détailler les exigences (dépendances) d'un paquet. Le requirements.txt (qui serait remplacé par le combo Pipfile / Pipfile.lock ici) devrait être utilisé pour répertorier les packages exacts qui seront utilisés pour satisfaire ce qui est requis, en fonction du métadonnées du setup.py , afin de créer un environnement reproductible.
Remplir les install_requires partir des requirements.txt revient à revenir en arrière.

setup.py 's install_requires =/= requirements.txt (ou Pipfile / Pipfile.lock ).
Pipfile (ou plutôt Pipfile.lock ) devrait être la seule source de vérité des packages à installer dans l'environnement de l'application.
setup.py install_requires fournit des métadonnées utilisées pour générer un Pipfile.lock valide.

Je pense que c'est de là que vient le frottement. J'espère que cela a du sens.

J'aime beaucoup cette réponse, Vincent, et je suis absolument d'accord sur le fait Pipfile.lock soit un remplacement complet (et meilleur) de requirements.txt .

Ayant utilisé Pipenv depuis quelques mois maintenant, cependant, mon utilisation de Pipfile me porte à penser que install_requires est vraiment presque identique à ce qui se passe dans le Pipfile . Si j'ai besoin numpy , j'ai pipenv install numpy et une nouvelle entrée entre dans le groupe [packages] de mon Pipfile : numpy = "*" . En d'autres termes, mon utilisation est totalement différente de requirements.txt , que j'avais l'habitude de générer avant de valider en utilisant pip freeze > requirements.txt .

C'est peut-être juste une façon particulière d'utiliser Pipenv, et je vais à contre-courant (j'installe également mon virtualenv dans .venv/ dans le répertoire du projet, donc je suis un voyou Pythonista), dans lequel cas, je peux facilement me conformer à la convention de la communauté Python d'avoir un mur de séparation entre setup.py et Pipfile | Pipfile.lock | requirements.txt .

Qu'est-ce qui me manque ici, @vphilippon ?

Merci pour l'info, @vphilippon. Peut-être que nous allons à l'envers, il semble que ce que nous voulons vraiment est l'inverse - une façon d'utiliser des deps abstraits de install_requires dans notre Pipfile, comme Donald le mentionne à propos de -e . dans le requirements.txt . Il semble qu'il y avait déjà un problème à ce sujet (# 339), mais cela ne semblait aller nulle part.

Est-ce déjà couvert par la syntaxe Pipfile ? Je viens de remarquer que la bibliothèque de requêtes Pipfile utilise "e1839a8" = {path = ".", editable = true, extras=["socks"]} dans sa section packages. Quelque chose de similaire est apparent dans les exemples Pipfile , mais je ne vois aucune autre documentation.

Tout d'abord, avis de non-responsabilité : mon expertise concerne principalement les packages lib. Je risque de rater certains points. J'ai le droit d'avoir tort, et je suis prêt à l'utiliser !
De plus, cela m'a fait me gratter la tête à quelques reprises. J'aimerais vraiment avoir un avis là-dessus.

Maintenant, venons-en à ça.

Je vais commencer par cette déclaration @elgertam :

[...] mon utilisation de Pipfile me fait penser que install_requires est vraiment presque identique à ce qui se passe dans le Pipfile. Si j'ai besoin de numpy, j'installe pipenv numpy et une nouvelle entrée entre dans le groupe [packages] de mon Pipfile [...]

Vous avez ajouté numpy à votre environnement, vous n'avez pas ajouté numpy aux dépendances de votre application.
Ce sont deux choses différentes. Continuez à lire, vous verrez ce que je veux dire.

En d'autres termes, mon utilisation est totalement différente de requirements.txt, que j'avais l'habitude de générer avant de valider en utilisant pip freeze > requirements.txt.

Étonnamment, votre utilisation n'est pas si différente si vous y réfléchissez :

  • Votre flux de travail précédent : pip install stuff -> pip freeze > requirements.txt -> flux install_requires partir de requirements.txt
  • Votre nouveau flux de travail (tenté) : pipenv install stuff -> Pipfile automatiquement mis à jour -> essaie d'alimenter install_requires avec le Pipfile .
  • Quelle est l'idée prévue : ajoutez des éléments à install_requires -> pipenv install -> Environnement et Pipfile.lock sont mis à jour.

Et pour cette façon de travailler, vous voulez un Pipfile qui indique que vous voulez installer votre application.
Quelque chose comme le requests Pipfile lié par @isobit.

Ou, un exemple :

[[source]]
url = "https://pypi.python.org/simple"
verify_ssl = true

[dev-packages]
pytest = ">=2.8.0"
tox = "*"

[packages]
"-e ." = "*"

Votre Pipfile sert à décrire votre environnement, pas les dépendances d'un paquet. Comme vous le voyez, le Pipfile ci-dessus définit ce que je veux installer, qui est le package local en mode modifiable.

Cela peut sembler un peu "inutile", car pour le moment tout est piloté par un seul paquet, mais disons que vous voulez installer votre application, mais avec requests[security] , mais ce n'est pas une dépendance stricte de votre application, vous faites pipenv install requests[security] , puis :

[[source]]
url = "https://pypi.python.org/simple"
verify_ssl = true

[dev-packages]
pytest = ">=2.8.0"
tox = "*"

[packages]
"-e ." = "*"
requests = { extras = ['security'] }

Et voilà, voici un exemple de la différence entre vos exigences abstraites et vos exigences concrètes. Il en va de même si vous vouliez installer gunicorn ou tout autre élément nécessaire dans l'environnement, mais cela ne fait pas partie de l'application elle-même.

Qu'est-ce qui me manque ici, @vphilippon ? Pourquoi les [packages] de Pipfile sont-ils trop limités pour être utilisés dans install_requires ou tests_require ?

Si je l'ai assez bien expliqué, vous pouvez voir que c'est juste censé être l'inverse.
Vous mettez vos dépendances dans install_requires , vous mettez votre package dans le Pipfile , puis vous obtenez un environnement, avec un Pipfile.lock pour la reproductibilité (car il résoudra et respectera votre dépendances du paquet).

Pour test_require , j'avoue que je ne suis pas sûr que ça rentre dans tout ça. IIRC, c'est une caractéristique spécifique setuptools . Nous pourrions dire qu'il s'agit d'un ensemble de dépendances abstraites pour les tests, et nous attendre à ce que pipenv résolve et installe celles qui font ensuite pipenv install --dev , pour tous les packages, mais j'ai l'impression que ce n'est pas tout à fait correct. Je n'ai pas d'idée ou d'opinion claire à ce sujet et sur la justification qui l'entoure, désolé.

J'espère que tout cela a du sens d'une manière ou d'une autre.

@vphilippon Vous l'avez assez bien expliqué, et je pense que vous m'avez convaincu.

TL; DR : Spécifiez les dépendances abstraites et absolument nécessaires dans setup.py , puis ajoutez du contexte (et donc du concret) dans Pipfile et Pipfile.lock , y compris le fantastique "-e ." = "*" Entrée

Un problème avec https://github.com/kennethreitz/pipenv/issues/209#issuecomment -337409290 est que lorsque nous voulons déployer notre application sur un serveur, nous n'obtenons pas un environnement reproductible.

Je veux dire normalement, lors du développement d'une _bibliothèque_ qui sera utilisée dans d'autres projets, nous voulons que notre install_requires soit assez lâche (=pas de liaison aux versions exactes). Oui. Mais lorsque nous construisons une application Web (ou n'importe quelle application) et que nous la déployons sur un serveur distant ou un conteneur Docker, nous voulons probablement des dépendances fixes. Même si nous spécifions des versions exactes dans install_requires , les dépendances transitives ne sont pas verrouillées et l'installation peut en fait télécharger une version différente (plus récente) d'une dépendance transitive, ce qui peut interrompre votre déploiement.

(Déclarer manuellement les versions exactes des dépendances transitives n'est pas une option - beaucoup trop lourd.)

Dans ce cas d'utilisation, nous devons dépendre d'un fichier de verrouillage de style requirements.txt (qui spécifie les versions exactes même pour les dépendances transitives). Cependant, il ne semble pas que pipenv permette d'exclure les exigences de développement dans pipenv lock -r (par exemple, pipenv lock --no-dev -r ), de sorte que nous puissions réellement créer de tels requirements.txt (qui peuvent alors être lu dans install_requires ) ?

Je cite l'article de Donald Stufft :

Une application a généralement un ensemble de dépendances, souvent même un ensemble très complexe de dépendances, contre lesquelles elle a été testée. Étant une instance spécifique qui a été déployée, elle n'a généralement pas de nom, ni aucune des autres métadonnées liées à l'empaquetage. Cela se reflète dans les capacités d'un fichier d'exigences pip.

En d'autres termes : l'application n'est pas le package. L'application est l'environnement, avec un ensemble de dépendances concrètes installées. Les dépendances d'une application doivent être représentées par un requirements.txt (ou Pipfile / Pipfile.lock ), pas un seul package install_requires .

Personnellement, j'irais jusqu'à dire que l'ensemble complet des dépendances épinglées (y compris la dépendance transitive) devrait être dans un requirements.txt pour l'application, pas dans le setup.py du package. Cela décrit l'idée que le déploiement d'une application ne se fait pas avec pip install myapp==1.0.0 , mais plutôt pip install -r requirements.txt (ou pipenv install avec un Pipfile.lock ), où le requirements.txt inclut myapp==1.0.0 ainsi que toutes les autres dépendances et dépendances transitives, épinglées.
Il peut sembler que je vais un peu loin, mais j'ai travaillé dans un contexte où "l'application" déployée est pilotée par un ensemble de packages. Il n'y a pas un seul package qui représente l'application elle-même, donc cette notion que "le package n'est pas l'application" m'a été jetée à la figure assez tôt 😄 .

J'ai un fort sentiment que Pipenv/Pipfile/Pipfile.lock suit cette idée.
Ce serait pourquoi il semble y avoir un écart pour passer de Pipfile.lock à setup.py 's install_requires : ce n'est vraiment pas censé être fait de cette façon, en tout cas.

@maintainers J'aimerais avoir votre avis ici pour savoir si c'est bien ainsi que vous voyez tout cela. J'ai prêché une vision de la façon dont nous devrions traiter les dépendances, mais je ne veux pas non plus parler à votre place.

@vphilippon Je pense qu'il y a différents points de vue et terminologie. Mais finalement, nous voulons une liste de dépendances épinglées à installer. Donc, un requirements.txt avec des versions épinglées (ou un paquet avec de telles dépendances déclarées, n'a pas vraiment d'importance). La question est de savoir comment créer réellement un tel fichier?

Avec pip-compile (de pip-tools ), je peux compiler ces requirements.txt partir de requirements.in et il ne contiendra que les dépendances non-dev dont mon application a besoin. Je ne sais pas si j'interprète correctement votre réponse - voulez-vous vraiment dire que nous devrions maintenir des dépendances épinglées requirements.txt à la main (en dupliquant également légèrement ce qui est déjà dans setup.py ), également pour dépendances transitives ? Ça ne peut pas être la solution...

S'il y avait pipenv lock --no-dev -r , je pense que cela résoudrait ce problème.

@tuukkamustonen Désolé pour la confusion, je ne parlais vraiment que de l'idée du install_requires vs requirements.txt / Pipfile / Pipfile.lock .

Ainsi, un requirements.txt avec des versions épinglées (ou un package avec de telles dépendances déclarées, n'a pas vraiment d'importance).

Je pense que la distinction est vraiment importante, mais comme vous l'avez dit, il y a ici différents points de vue. Acceptons d'être en désaccord pour l'instant. En passant, ce serait bien d'avoir un endroit pour continuer sur le sujet sans ajouter de bruit à un problème spécifique. C'est le genre de choses qui ont besoin de plus de discussion et de partage dans la communauté, IMO.

Cependant, il ne semble pas que pipenv permette d'exclure les exigences de développement dans pipenv lock -r

Mais finalement, nous voulons une liste de dépendances épinglées à installer. [...] La question est, comment fabriquer réellement un tel fichier ? [...] Avec pip-compile (de pip-tools), je peux compiler un tel requirements.txt à partir de requirements.in et il ne contiendra que les dépendances non-dev dont mon application a besoin.

Ah, j'ai sauté cette partie au début, désolé. Et il semble que vous ayez raison : je ne suis pas en mesure de trouver un moyen de dire pipenv install --not-dev-stuff (j'étais à peu près sûr qu'il y en avait un, bizarre) et de générer un environnement non-développeur. Quel est l'intérêt d'avoir une 2 section distincte alors? Il me manque peut-être quelque chose maintenant, et ce n'est pas lié à l'utilisation avec setup.py . Cela vaut peut-être la peine d'en parler dans un nouveau numéro.

ÉDITER:
J'ai fait une erreur ici. En effet, je n'ai pas trouvé de moyen de générer un Pipfile.lock sans packages de développement, mais , dans un nouvel environnement, avec Pipfile / Pipfile.lock existant, faire pipenv install n'installe pas les packages de développement. Cela ne résout pas le problème de @tuukkamustonen , mais je me suis trompé en déclarant qu'il n'y avait aucun moyen d'installer un "environnement prod", mon erreur.

Ouf, c'était beaucoup à rattraper.

Sauf erreur de ma part, le code dans # 209 (commentaire) peut être utilisé en toute sécurité si vous construisez une roue (= dist binaire), mais pas si vous construisez sdist (= dist source).

@tuukkamustonen ceci est destiné uniquement à être utilisé dans un script autonome pour les déploiements, ne l'incluez pas dans votre setup.py. Il s'agit d'une solution de contournement semi-hacky d'avant que nous ayons eu pipenv lock -r il y a plusieurs mois. Cette approche fonctionnera pour votre cas d'utilisation de fractionnement de packages et dev-packages .

J'utilise personnellement (3) (voir # 209 (commentaire)) jusqu'à ce que Pipfile devienne plus un standard commun, auquel cas aucun de mes projets ne dépendra directement du code Pipenv, car Pipenv semble clairement destiné à être un outil de gestion d'un virtualenv basé sur un Pipfile, et pas nécessairement une bibliothèque Pipfile elle-même.

@elgertam il semble que vos opinions aient été influencées depuis ce commentaire, mais je noterais que ce n'est probablement pas une bonne idée de regrouper pipenv avec votre projet. Rien n'interdit explicitement cela, mais nous effectuons de nombreux correctifs de chemin qui sont susceptibles de causer des problèmes lorsqu'ils sont utilisés de cette manière. Je suppose que je vais simplement envelopper cela avec un avertissement "à utiliser à vos risques et périls".

mainteneurs, j'aimerais avoir votre avis ici pour savoir si c'est bien ainsi que vous voyez tout cela. J'ai prêché une vision de la façon dont nous devrions traiter les dépendances, mais je ne veux pas non plus parler à votre place.

Je pense que vous êtes assez en phase avec ce que notre vision a été pendant toute la durée du projet. Merci d'avoir compilé tout cela et de l'avoir si bien articulé @vphilippon !

Il semble que les autres parties pertinentes de cette discussion aient été déplacées dans le # 942, donc je pense que nous sommes bons ici. S'il vous plaît ping moi si je n'ai rien abordé.

J'ai suivi avec une proposition concrète dans https://github.com/pypa/pipfile/issues/98 qui, je crois, nous donne quelque chose d'actionnable et de pragmatique qui pourrait améliorer DX pour la maintenance des bibliothèques Python.

Les pensées?

import json, jmespath

install_requires = []
with open('Pipfile.lock') as f:
    context = json.loads(f.read())
    install_requires.extend(map(
        lambda n, v : n + v,
        jmespath.search('default | keys(@)', context),
        jmespath.search('default.*.version', context),
    ))

setup(
    name='foobar',
    packages=find_packages(),
    setup_requires=['jmespath'],
    install_requires=install_requires,
)

@cornfeedhobo, je crois comprendre que setup_requires ne fonctionne pas bien avec pip. Pourriez-vous expliquer un peu comment vous suggéreriez d'utiliser cet échantillon ?

L'exemple ne fonctionnera que si vous installez d'abord jmespath car setup.py est évalué comme du code Python normal. L'argument setup_requires n'aboutit à rien : si le programme va aussi loin, jmespath est assuré d'être installé.

J'ai mentionné cela dans un autre numéro, mais je ne peux pas le localiser (il y a tellement de discussions en double partout dans le suivi des problèmes qu'il est impossible de trouver quoi que ce soit), alors je le répète : veuillez ne rien mettre de non construit- dans setup.py à moins que vous ne fournissiez une solution de secours appropriée ou que vous ayez une raison parfaite. Un paquet contenant le setup.py ci-dessus ne fonctionnera même pas avec Pipenv avec jmespath installé dans le virtualenv ; Pipenv invoque setup.py egg_info dans un environnement propre et ne parviendra pas à exécuter l'importation jmespath. C'est une mauvaise pratique. Veuillez l'éviter.

@epot je n'étais pas au courant de ça

@uranusjr Merci pour la réponse bien pensée avec des détails. Je ne fais qu'explorer toute cette question, donc je pourrais revenir pour plus d'embarras. Je suis aussi pypa/pipfile#98

Et si nous n'avons pas besoin jmespath ?

import json


install_requires = []
tests_require = []

with open('Pipfile.lock') as fd:
    lock_data = json.load(fd)
    install_requires = [
        package_name + package_data['version']
        for package_name, package_data in lock_data['default'].items()
    ]
    tests_require = [
        package_name + package_data['version']
        for package_name, package_data in lock_data['develop'].items()
    ]

@mschwager Vous ne voulez pas épingler la version, sinon les utilisateurs auront du mal. #1921 est un exemple d'une bibliothèque utilisant == qui finit par casser la construction d'un utilisateur.

Mes excuses, mais quelle est la différence entre utiliser setup.py pour l'utiliser comme un package ou requirements.txt / Pipfile pour gérer les dépendances dudit package ? Les bibliothèques requises DOIVENT être identiques entre setup.py et requirements.txt / Pipfile , n'est-ce pas ? Il n'y a donc aucune raison de ne pas intégrer Pipfile . setup.py analyse déjà requirements.txt . Pourquoi ne devrait-il pas être capable d'analyser Pipfile ?

Ce serait bien de se débarrasser de requirements.txt et d'utiliser simplement Pipfile

Non, il n'y a aucune raison qu'ils soient identiques. C'est une hypothèse assez radicale, et beaucoup dans la communauté ne seraient pas d'accord.

Il y a en effet, cependant, des raisons pour lesquelles ils _peuvent_ être identiques. Pipenv n'exclut pas cela. C'est juste hors de portée et non pris en charge par ce projet. Vous pouvez totalement créer une bibliothèque pour prendre en charge cela et tirer parti de PEP 518 , qui est implrmrneted dans pip 10.0, pour fournir une prise en charge au moment de la construction.

Comme vous l'avez dit, il n'y a aucune raison de ne pas autoriser setup.py à analyser Pipfile. J'ai hâte que tu réalises ça :)

Comprenez que certaines personnes aiment les bibliothèques abstraites de setup.py mais que ce n'est pas un must? Je veux dire que golang ne souffre que d'exigences concrètes, mais qu'il est toujours capable de remplacer une bibliothèque requise par votre propre fork simplement parce qu'elle correspond au nom? Il est compréhensible que l'intégration de setup.py ne soit tout simplement pas dans la portée.

Cependant, il serait intéressant de voir quelle est la feuille de route à long terme de pipenv. Ce serait formidable de le voir devenir l'outil incontournable en python. par exemple remplace en quelque sorte setup.py ou génère un setup.py approprié pour l'utilisateur, de toute façon pipenv étant de facto gestionnaire de paquets est génial. Je me demande simplement s'il est possible d'étendre la portée pour inclure setup.py ?

Si pipenv est comme npm etc., alors leur package.json permet l'installation à distance, aucune raison pour que pipenv ne puisse pas interagir ou remplacer setup.py, ce qui le rend dans la portée. Est-ce que j'ai du sens ou est-ce que j'ai l'impression de prendre des pilules folles ?

Merci de penser que c'est un incontournable. Considérant que c'est si crucial, je pense que nous pourrons exécuter un système de construction basé sur Pipfile en un rien de temps.

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