J'ai un requirements.txt
fichier que j'utilise avec Travis-CI. Il semble stupide de dupliquer les exigences dans les deux requirements.txt
et setup.py
, donc j'espérais passer un install_requires
descripteur de fichier au kwarg dans setuptools.setup
.
Est-ce possible? Si oui, comment dois-je procéder?
Voici mon requirements.txt
dossier:
guessit>=0.5.2
tvdb_api>=1.8.2
hachoir-metadata>=1.3.3
hachoir-core>=1.3.3
hachoir-parser>=1.3.4
install_requires
est utilisé pour déclarer les dépendances sur les packages qui sont nécessaires au fonctionnement du package et sont utilisées par le développeur du package, tandis qu'ilrequirements.txt
est utilisé pour automatiser l'installation des environnements, qui permet d'installer des logiciels supplémentaires et d'effectuer l'épinglage de version et est utilisé par les administrateurs système déployant le paquet. Leur rôle et leur public cible diffèrent considérablement, donc essayer de les combiner comme le souhaite OP est une véritable erreur de conception.[line.strip() for line in open("requirements.txt").readlines()]
?pkg_resources.parse_requirements()
Réponses:
Vous pouvez le retourner et répertorier les dépendances dans
setup.py
et avoir un seul caractère - un point.
- à larequirements.txt
place.Alternativement, même si cela n'est pas conseillé, il est toujours possible d'analyser le
requirements.txt
fichier (s'il ne fait référence à aucune exigence externe par URL) avec le hack suivant (testé avecpip 9.0.1
):Cependant, cela ne filtre pas les marqueurs d'environnement .
Dans les anciennes versions de pip, plus spécifiquement antérieures à 6.0 , il existe une API publique qui peut être utilisée pour y parvenir. Un fichier d'exigences peut contenir des commentaires (
#
) et peut inclure d'autres fichiers (--requirement
ou-r
). Ainsi, si vous voulez vraiment analyser un,requirements.txt
vous pouvez utiliser l'analyseur pip:la source
setup(..., dependency_links=[str(req_line.url) for req_line in parse_requirements(<requirements_path>)], ...)
pip
défaut, l'analyse des dépendancessetup.py
en l'absence derequirements.txt
, la réponse simple astucieusement notée par Tobu ci-dessous est de répertorier toutes les dépendances danssetup.py
et de les supprimerrequirements.txt
. Pour les applications nécessitant les deux, réduisez simplement la liste des dépendancesrequirements.txt
au simple.
caractère. Terminé.A première vue, il ne semble que
requirements.txt
etsetup.py
sont des doublons stupides, mais il est important de comprendre que si la forme est similaire, la fonction prévue est très différente.Le but d'un auteur de package, lors de la spécification des dépendances, est de dire "partout où vous installez ce package, ce sont les autres packages dont vous avez besoin, pour que ce package fonctionne."
En revanche, l'auteur du déploiement (qui peut être la même personne à un moment différent) a un travail différent, en ce sens qu'il dit "voici la liste des packages que nous avons rassemblés et testés et que je dois maintenant installer".
L'auteur du package écrit pour une grande variété de scénarios, car ils mettent leur travail à disposition de manière qu'ils ne connaissent peut-être pas et n'ont aucun moyen de savoir quels packages seront installés à côté de leur package. Afin d'être un bon voisin et d'éviter les conflits de versions de dépendances avec d'autres packages, ils doivent spécifier une gamme de versions de dépendances aussi large que possible. C'est ce que
install_requires
dans lesetup.py
fait.L'auteur du déploiement écrit pour un objectif très différent et très spécifique: une seule instance d'une application ou d'un service installé, installé sur un ordinateur particulier. Afin de contrôler précisément un déploiement et d'être sûr que les bons packages sont testés et déployés, l'auteur du déploiement doit spécifier la version exacte et l'emplacement source de chaque package à installer, y compris les dépendances et les dépendances des dépendances. Avec cette spécification, un déploiement peut être appliqué de manière répétée à plusieurs machines, ou testé sur une machine de test, et l'auteur du déploiement peut être sûr que les mêmes packages sont déployés à chaque fois. C'est ce que
requirements.txt
fait un .Vous pouvez donc voir que, bien qu'ils ressemblent tous les deux à une grande liste de packages et de versions, ces deux choses ont des tâches très différentes. Et c'est vraiment facile de mélanger cela et de se tromper! Mais la bonne façon de penser à cela est que
requirements.txt
c'est une "réponse" à la "question" posée par les exigences dans tous les différentssetup.py
fichiers de package. Plutôt que de l'écrire à la main, il est souvent généré en disant à pip de regarder tous lessetup.py
fichiers dans un ensemble de packages souhaités, de trouver un ensemble de packages qui, selon lui, répond à toutes les exigences, puis, après leur installation, "geler" "cette liste de packages dans un fichier texte (c'est de là quepip freeze
vient le nom).Donc, le point à retenir:
setup.py
devrait déclarer les versions de dépendances les plus lâches qui sont toujours utilisables. Son travail consiste à dire avec quoi un package particulier peut fonctionner.requirements.txt
est un manifeste de déploiement qui définit un travail d'installation complet et ne doit pas être considéré comme lié à un seul package. Son travail consiste à déclarer une liste exhaustive de tous les packages nécessaires pour faire fonctionner un déploiement.Références:
la source
requirements.txt
avec la source du package qui contient les exigences concrètes / figées pour l'installation ou le test. Certes ,setup.py
peut être utilisé à cet effet dans le projet lui - même? Je ne peux qu'imaginer utiliser un tel fichier pour les outils utilisés pour soutenir la gestion du projet (par exemple refactoring, création de versions, etc.).requirements.txt
y a plus de documentation sur l'état du monde qui a produit une construction donnée, même si elle n'est généralement pas utilisée dans le processus de construction lui-même? Ça a du sens. Cependant, il semble que plusieurs systèmes reposent sur la duplication: Travis installe certains (anciens) packages par défaut dans votre virtualenv et dit d'utiliserrequirements.txt
. Si je demande comment s'assurer que les dépendances sont utilisées au plus tardsetup.py
, les gens insistent pour que je les utiliserequirements.txt
.Il ne peut pas prendre de descripteur de fichier. L'
install_requires
argument ne peut être qu'une chaîne ou une liste de chaînes .Vous pouvez bien sûr lire votre fichier dans le script de configuration et le transmettre sous forme de liste de chaînes à
install_requires
.la source
install_requires
. Cependant, cela ne fonctionne pas si vous n'utilisez pas de syntaxe déclarative.setup.py
est un programme qui doit être exécuté, pas un fichier de données qui doit être analysé. Cela n'empire pas cette réponse.include requirements.txt
dans votreMANIFEST.in
ou vous ne pourrez pas installer votre bibliothèque à partir d'une distribution source.Les fichiers d'exigences utilisent un format pip étendu, qui n'est utile que si vous avez besoin de compléter votre
setup.py
avec des contraintes plus fortes, par exemple en spécifiant les URL exactes dont certaines dépendances doivent provenir, ou la sortie depip freeze
pour figer l'ensemble du package en mode connu. versions. Si vous n'avez pas besoin des contraintes supplémentaires, utilisez uniquement asetup.py
. Si vous sentez que vous avez vraiment besoin d'en expédier un derequirements.txt
toute façon, vous pouvez en faire une seule ligne:Il sera valide et fera exactement référence au contenu de celui
setup.py
qui se trouve dans le même répertoire.la source
pip install -r requirements.txt
) sans installer le package lui-même?-e .
devrait suffire. Consultez cette page: caremad.io/posts/2013/07/setup-vs-requirementBien que ce ne soit pas une réponse exacte à la question, je recommande le billet de blog de Donald Stufft à https://caremad.io/2013/07/setup-vs-requirement/ pour une bonne interprétation de ce problème. Je l'utilise avec beaucoup de succès.
Bref, ce
requirements.txt
n'est pas unesetup.py
alternative, mais un complément de déploiement. Conservez une abstraction appropriée des dépendances des packages danssetup.py
. Définissez unrequirements.txt
ou plusieurs d'entre eux pour récupérer des versions spécifiques des dépendances de package pour le développement, les tests ou la production.Par exemple, avec des packages inclus dans le repo sous
deps/
:pip exécute les packages
setup.py
et installe les versions spécifiques des dépendances déclarées dansinstall_requires
. Il n'y a aucune duplicité et le but des deux artefacts est préservé.la source
pip install my-package
. Si les dépendances de my-package ne sont pas répertoriées dans my-package / setup.py, elles ne sont pas installées parpip install my-package
. Je n'ai pas pu déterminer comment fournir un package pour d'autres qui inclut des dépendances sans les indiquer explicitement dans setup.py. J'aimerais savoir si quelqu'un a compris comment le garder au sec tout en permettant aux autres d'installer les dépendances my-package + sans télécharger le fichier d'exigences et appeler manuellementpip install -r my-package/requirements.txt
.requirements.txt
. Exactement. Mise à jour de la question pour clarifier les choses. Lien de mise à jour du blog obsolète également mis à jour.L'utilisation
parse_requirements
est problématique car l'API pip n'est pas documentée et prise en charge publiquement. Dans le pip 1.6, cette fonction est en train de se déplacer, de sorte que les utilisations existantes de celle-ci risquent de se casser.Un moyen plus fiable pour éliminer la duplication entre
setup.py
etrequirements.txt
consiste à spécifier vos dépendances danssetup.py
, puis à les placer-e .
dans votrerequirements.txt
fichier. Certaines informations d'un despip
développeurs sur les raisons pour lesquelles c'est une meilleure façon de procéder sont disponibles ici: https://caremad.io/blog/setup-vs-requirement/la source
La plupart des autres réponses ci-dessus ne fonctionnent pas avec la version actuelle de l'API de pip. Voici la façon * correcte de le faire avec la version actuelle de pip (6.0.8 au moment de la rédaction, fonctionnait également en 7.1.2. Vous pouvez vérifier votre version avec pip -V).
* Correct, en ce sens que c'est la façon d'utiliser parse_requirements avec le pip actuel. Ce n'est probablement pas la meilleure façon de le faire, car, comme l'ont indiqué les affiches ci-dessus, pip ne maintient pas vraiment une API.
la source
Installez le package actuel dans Travis. Cela évite l'utilisation d'un
requirements.txt
fichier. Par exemple:la source
pip freeze
et d'exporter ce fichier quelque part comme un artefact (comme S3 ou quelque chose), alors vous auriez un excellent moyen d'installer de manière répétitive exactement ce que vous testé.from pip.req import parse_requirements
n'a pas fonctionné pour moi et je pense que c'est pour les lignes vides dans mon requirements.txt, mais cette fonction fonctionnela source
Si vous ne voulez pas forcer vos utilisateurs à installer pip, vous pouvez émuler son comportement avec ceci:
la source
L'interface suivante est devenue obsolète dans pip 10:
Je l'ai donc commuté juste en simple analyse de texte:
la source
pathlib
variante .Cette approche simple lit le fichier des exigences à partir de
setup.py
. Il s'agit d'une variante de la réponse de Dmitiry S .. Cette réponse est compatible uniquement avec Python 3.6+.Par DS ,
requirements.txt
peut documenter des exigences concrètes avec des numéros de version spécifiques, tandis quesetup.py
peut documenter des exigences abstraites avec des plages de versions lâches.Ci-dessous est un extrait de mon
setup.py
.Notez que
distutils.text_file.TextFile
cela supprimera les commentaires. De plus, d'après mon expérience, vous n'avez apparemment pas besoin de prendre de mesure spéciale pour regrouper le fichier des exigences.la source
ATTENTION AU
parse_requirements
COMPORTEMENT!Veuillez noter que
pip.req.parse_requirements
les traits de soulignement seront remplacés par des tirets. Cela me rendait furieux pendant quelques jours avant de le découvrir. Exemple démontrant:produit
la source
[ir.req.unsafe_name for ir in req_deps if ir.req is not None]
J'ai créé une fonction réutilisable pour cela. Il analyse en fait tout un répertoire de fichiers d'exigences et les définit sur extras_require.
Le dernier toujours disponible ici: https://gist.github.com/akatrevorjay/293c26fefa24a7b812f5
la source
pip._internal
... Si vous ne fournissez pas d'API externe utilisable, vous ne devriez pas casser tous ceux qui utilisent tout ce que vous fournissez.Une autre solution possible ...
et ensuite utiliser ...
la source
tree
vient-il?Je ne recommanderais pas de faire une telle chose. Comme mentionné plusieurs fois
install_requires
et nerequirements.txt
sont certainement pas censés être la même liste. Mais comme il y a beaucoup de réponses trompeuses tout autour impliquant des API internes privées de pip , il pourrait être utile de chercher des alternatives plus sûres ...Il n'est pas nécessaire que pip analyse un
requirements.txt
fichier à partir d'un script setuptoolssetup.py
. Le projet setuptools contient déjà tous les outils nécessaires dans son package de niveau supérieurpkg_resources
.Cela pourrait plus ou moins ressembler à ceci:
la source
pip
l'analyse syntaxique et nonpkg_resources
depuis avant 2015 sont des bogues tels que github.com/pypa/setuptools/issues/470 . Celui-ci est corrigé de nos jours, mais j'ai toujours un peu peur de l'utiliser, car les deux implémentations semblent être développées séparément.Cross poster ma réponse de cette question SO pour une autre solution simple, à l'épreuve de la version pip.
Ensuite, ajoutez simplement toutes vos exigences sous le
requirements.txt
répertoire racine du projet.la source
J'ai fait ça:
la source
Encore un autre
parse_requirements
hack qui analyse également les marqueurs d'environnement enextras_require
:Il devrait prendre en charge les distances sdist et binaires.
Comme indiqué par d'autres,
parse_requirements
présente plusieurs lacunes, ce n'est donc pas ce que vous devez faire sur des projets publics, mais cela peut suffire pour des projets internes / personnels.la source
parse_requirements()
, donc cela échoue maintenant.Voici un hack complet (testé avec
pip 9.0.1
) basé sur la réponse de Romain qui l'analyserequirements.txt
et le filtre en fonction des marqueurs d'environnement actuels :la source
r.match_markers()
vous êtes en train d'évaluer les marqueurs, ce qui est correct pour un sdist. Cependant, si vous construisez une dist binaire (par exemple une roue), le package ne listera que les bibliothèques qui correspondent à votre environnement de construction.wheel environment
(si c'est la chose que la personne essaie de faire) pour évaluer les marqueurs par rapport à cela?bdist_wheel
. Il n'évalue pas les marqueurs, il les ajoute simplementextras_require
.