J'ai commencé à travailler avec Python. J'ai ajouté requirements.txt
et setup.py
à mon projet. Mais je suis toujours confus quant au but des deux fichiers. J'ai lu qui setup.py
est conçu pour les choses redistribuables et qui requirements.txt
est conçu pour les choses non redistribuables. Mais je ne suis pas certain que ce soit exact.
Comment ces deux fichiers sont-ils vraiment destinés à être utilisés?
Réponses:
requirements.txt
Cela vous aide à configurer votre environnement de développement. Des programmes tels que
pip
peuvent être utilisés pour installer tous les packages répertoriés dans le fichier d'un seul coup. Après cela, vous pouvez commencer à développer votre script python. Particulièrement utile si vous prévoyez que d'autres contribuent au développement ou utilisent des environnements virtuels. Voici comment vous l'utilisez:setup.py
Cela vous permet de créer des packages que vous pouvez redistribuer. Ce script est destiné à installer votre package sur le système de l'utilisateur final et non à préparer l'environnement de développement comme le
pip install -r requirements.txt
fait. Consultez cette réponse pour plus de détails sur setup.py.Les dépendances de votre projet sont répertoriées dans les deux fichiers.
la source
La réponse courte est que
requirements.txt
c'est pour lister les exigences des packages uniquement.setup.py
d'autre part, c'est plus comme un script d'installation. Si vous ne prévoyez pas d'installer le code python, vous n'aurez généralement besoin que derequirements.txt
.Le fichier
setup.py
décrit, en plus des dépendances du package, l'ensemble des fichiers et des modules qui doivent être packagés (ou compilés, dans le cas des modules natifs (c'est-à-dire écrits en C)), et les métadonnées à ajouter aux listes de packages python ( ex. nom du package, version du package, description du package, auteur, ...).Étant donné que les deux fichiers répertorient les dépendances, cela peut entraîner un peu de duplication. Lisez ci-dessous pour plus de détails.
requirements.txt
Ce fichier répertorie les exigences du package Python. Il s'agit d'un fichier texte brut (éventuellement avec des commentaires) qui répertorie les dépendances de package de votre projet python (une par ligne). Il ne décrit pas la manière dont votre package python est installé. Vous consommez généralement le fichier des exigences avec
pip install -r requirements.txt
.Le nom de fichier du fichier texte est arbitraire, mais est souvent
requirements.txt
par convention. Lorsque vous explorez les référentiels de code source d'autres packages python, vous pouvez tomber sur d'autres noms, tels quedev-dependencies.txt
oudependencies-dev.txt
. Celles-ci ont le même objectif,dependencies.txt
mais répertorient généralement des dépendances supplémentaires d'intérêt pour les développeurs du paquet particulier, à savoir pour tester le code source (par exemple pytest, pylint, etc.) avant la publication. Les utilisateurs du package n'ont généralement pas besoin de l'ensemble complet de dépendances de développeur pour exécuter le package.Si plusieurs
requirements-X.txt
variantes sont présentes, l'une répertoriera généralement les dépendances d'exécution et l'autre au moment de la construction ou testera les dépendances. Certains projets mettent également en cascade leur fichier d'exigences, c'est-à-dire lorsqu'un fichier d'exigences comprend un autre fichier ( exemple ). Cela peut réduire la répétition.setup.py
Il s'agit d'un script python qui utilise le
setuptools
module pour définir un package python (nom, fichiers inclus, métadonnées du package et installation). Il listerarequirements.txt
également les dépendances d'exécution du package. Setuptools est le moyen de facto de construire et d'installer des paquets python, mais il a ses défauts, qui au fil du temps ont poussé au développement de nouveaux «gestionnaires de méta-paquets», comme pip. Des exemples de défauts de setuptools sont son incapacité à installer plusieurs versions du même package et l'absence de commande de désinstallation.Lorsqu'un utilisateur python le fait
pip install ./pkgdir_my_module
(oupip install my-module
), pip s'exécuterasetup.py
dans le répertoire (ou module) donné. De même, tout module qui a unsetup.py
peut êtrepip
-installé, par exemple en s'exécutant àpip install .
partir du même dossier.Ai-je vraiment besoin des deux?
La réponse courte est non, mais c'est bien d'avoir les deux. Ils atteignent des objectifs différents, mais ils peuvent tous deux être utilisés pour répertorier vos dépendances.
Vous pouvez envisager une astuce pour éviter de dupliquer votre liste de dépendances entre
requirements.txt
etsetup.py
. Si vous avez déjà écrit unsetup.py
package entièrement fonctionnel pour votre package et que vos dépendances sont principalement externes, vous pouvez envisager d'avoir une version simplerequirements.txt
avec uniquement les éléments suivants:Il
-e
s'agit d'unepip install
option spéciale qui installe le package donné en mode modifiable . Quandpip -r requirements.txt
est exécuté sur ce fichier, pip installera vos dépendances via la liste dans./setup.py
. L'option modifiable placera un lien symbolique dans votre répertoire d'installation (au lieu d'un œuf ou d'une copie archivée). Il permet aux développeurs de modifier le code en place à partir du référentiel sans le réinstaller.Vous pouvez également profiter de ce qu'on appelle les "extras setuptools" lorsque vous avez les deux fichiers dans votre référentiel de packages. Vous pouvez définir des packages facultatifs dans setup.py sous une catégorie personnalisée et installer ces packages à partir de cette catégorie uniquement avec pip:
puis, dans le fichier des exigences:
Cela conserverait toutes vos listes de dépendances dans setup.py.
Remarque : vous exécutez normalement pip et setup.py à partir d'un bac à sable, comme ceux créés avec le programme
virtualenv
. Cela évitera d'installer des packages python en dehors du contexte de l'environnement de développement de votre projet.la source
.
w / o à l'-e
intérieurrequirements.txt
. Cette méthode délègue simplement toutes les exigences àsetup.py
et vous n'avez pas besoin de forcer qui que ce soit en mode modifiable. Les utilisateurs peuvent toujours le fairepip install -e .
s'ils le souhaitent.-e .
utilise également setup.py pour trouver les dépendances, mais lie le dossier actuel (en place, avec un lien symbolique) dans le dossier d'installation de pip, plutôt que de prendre une copie - vous n'utiliseriez-e
généralement que si vous développez le package. Avec-e
, les modifications apportées à vos fichiers de package python (* .py) prendraient effet immédiatement dans votre environnement pip, plutôt que d'avoir à forcer la réinstallation du package après chaque modification.cd foo && pip install -r ./bar/requirements.txt
va - t-il rechercher setup.py dansfoo/bar
oufoo
? Si c'est le dernier, y a-t-il un moyen d'atteindre le premier?pip -r REQ
ne se soucie pas du répertoire dans lequel se trouve REQ. Vous pouvez l' alimenter à partir d' un fifo même si vous voulez:pip install -r <(echo "mylib1"; echo "mylib2";)
. Où<(CMD)
est la substitution de commande bash, pas la redirection stdin.Par souci d'exhaustivité, voici comment je le vois sous
34 angles différents.Voici la description précise citée de la documentation officielle (c'est moi qui souligne):
Mais cela peut encore ne pas être facile à comprendre, donc dans la section suivante, il y a 2 exemples factuels pour démontrer comment les 2 approches sont censées être utilisées, différemment.
Leurs usages réels sont donc (supposés être) différents
Si votre projet
foo
doit être publié en tant que bibliothèque autonome (ce qui signifie que d'autres le feraient probablementimport foo
), alors vous (et vos utilisateurs en aval) voudriez avoir une déclaration de dépendance flexible, de sorte que votre bibliothèque ne le fasse pas (et elle ne doit pas ) soyez "pointilleux" sur la version exacte de VOS dépendances. Donc, généralement, votre setup.py contient des lignes comme celle-ci:Si vous souhaitez simplement «documenter» ou «épingler» votre environnement actuel EXACT pour votre application
bar
, c'est-à-dire que vous ou vos utilisateurs souhaitez utiliser votre application telle quellebar
, c'est-à-dire en cours d'exécutionpython bar.py
, vous pouvez geler votre environnement afin qu'il se comporterait toujours de la même manière. Dans ce cas, votre fichier d'exigences ressemblerait à ceci:En réalité, lequel dois-je utiliser?
Si vous développez une application
bar
qui sera utilisée parpython bar.py
, même s'il ne s'agit que d'un "script pour le plaisir", il est toujours recommandé d'utiliser requirements.txt car, qui sait, la semaine prochaine (qui se trouve être Noël) vous recevrez un nouvel ordinateur en cadeau, vous devrez donc configurer à nouveau votre environnement exact.Si vous développez une bibliothèque
foo
qui sera utilisée parimport foo
, vous devez préparer un setup.py. Période. Mais vous pouvez toujours choisir de fournir également un requirements.txt en même temps, ce qui peut:(a) soit être dans le
A==1.2.3
style (comme expliqué au point 2 ci-dessus);(b) ou contiennent simplement un single magique
.
ce qui équivaudrait à peu près à "installer les exigences basées sur setup.py" sans duplication. Personnellement, je considère que cette dernière approche brouille la ligne, ajoute à la confusion et n'ajoute PAS vraiment de valeur, mais c'est néanmoins une astuce dérivée d'une approche mentionnée par le responsable de l'emballage Python, Donald dans son article de blog .
Différentes limites inférieures.
Même après avoir suivi les 3 critères ci-dessus et correctement décidé que votre bibliothèque
hybrid-engine
utiliserait asetup.py
pour déclarer sa dépendanceengine>=1.2.0
, et que votre exemple d'applicationreliable-car
utiliseraitrequirements.txt
pour déclarer sa dépendanceengine>=1.2.3
, même si la dernière version deengine
est déjà à 1.4.0. Comme vous le voyez, votre choix pour leur nombre limite inférieure est encore subtilement différent. Et voici pourquoi.hybrid-engine
dépend duengine>=1.2.0
fait que, hypothétiquement parlant, la capacité de "combustion interne" nécessaire a été introduite pour la première fois dansengine 1.2.0
, et cette capacité est la nécessité dehybrid-engine
, indépendamment du fait qu'il puisse y avoir des bogues (mineurs) dans cette version et a été corrigée dans les versions ultérieures 1.2.1 , 1.2.2 et 1.2.3.reliable-car
dépendengine>=1.2.3
parce que c'est la version la plus ancienne SANS problèmes connus, jusqu'à présent. Bien sûr, il y a de nouvelles capacités dans les versions ultérieures, par exemple, "moteur électrique" introduitengine 1.3.0
et "réacteur nucléaire" introduitengine 1.4.0
, mais elles ne sont pas nécessaires pour le projetreliable-car
.la source
A==1.2.3
, puis si le package en aval de votre bibliothèque dépendA==1.2.4
, il n'y aura plus moyen de satisfaire les deux. La solution pour minimiser ce conflit est que votre bibliothèque définit une plage dont vous savez qu'elle fonctionnera. En supposant que de nombreuses bibliothèques en amont suivent déjà semver.org ,A>=1,<2
cela fonctionnerait.foo
neimport foo
vous donner? La réponse acceptée par le piratage dans ce lien que vous avez fourni est un exemple parfait de la raison pour laquelle le responsable du paquet "ne devrait pas et ne doit pas être pointilleux". :-) Maintenant, puis-je avoir votre vote pour?