Comment personnaliser un requirements.txt pour plusieurs environnements?

112

J'ai deux branches, développement et production. Chacun a des dépendances, dont certaines sont différentes. Le développement pointe vers des dépendances qui sont elles-mêmes en développement. De même pour la production. Je dois déployer sur Heroku qui attend les dépendances de chaque branche dans un seul fichier appelé «requirements.txt».

Quelle est la meilleure façon de s'organiser?

Ce à quoi j'ai pensé:

  • Maintenir des fichiers d'exigences séparés, un dans chaque branche (doit survivre à des fusions fréquentes!)
  • Dites à Heroku quel fichier d'exigences je souhaite utiliser (variable d'environnement?)
  • Écrire des scripts de déploiement (créer une branche temporaire, modifier le fichier d'exigences, valider, déployer, supprimer une branche temporaire)
Charles R
la source
1
script de déploiement plus facile: maintenir 2 fichiers. utilisez un lien symbolique entre eux.
Udy

Réponses:

208

Vous pouvez mettre en cascade vos fichiers d'exigences et utiliser l'indicateur "-r" pour indiquer à pip d'inclure le contenu d'un fichier dans un autre. Vous pouvez diviser vos besoins dans une hiérarchie de dossiers modulaire comme ceci:

`-- django_project_root
|-- requirements
|   |-- common.txt
|   |-- dev.txt
|   `-- prod.txt
`-- requirements.txt

Le contenu des fichiers ressemblerait à ceci:

common.txt:

# Contains requirements common to all environments
req1==1.0
req2==1.0
req3==1.0
...

dev.txt:

# Specifies only dev-specific requirements
# But imports the common ones too
-r common.txt
dev_req==1.0
...

prod.txt:

# Same for prod...
-r common.txt
prod_req==1.0
...

En dehors de Heroku, vous pouvez désormais configurer des environnements comme celui-ci:

pip install -r requirements/dev.txt

ou

pip install -r requirements/prod.txt

Puisque Heroku recherche spécifiquement "requirements.txt" à la racine du projet, il devrait simplement refléter prod, comme ceci:

requirements.txt:

# Mirrors prod
-r requirements/prod.txt
Christian Abbott
la source
2
Vous avez ignoré le problème de l'utilisation de fichiers d'exigences séparés pour différents environnements sur heroku.
Ed J
29
Je crois que ma réponse a abordé cela.
Christian Abbott
1
Je cherchais un moyen d'avoir des exigences différentes sur Heroku pour la mise en scène (où je veux des packages de débogage supplémentaires) et l'environnement de production (où je n'ai pas besoin de ces packages de débogage). Malheureusement, comme l'a dit @EdJ, cette réponse ne répond pas à cela.
Antoine Pinsard
1
Je pourrais mal comprendre votre question ou peut-être que votre question est différente de celle de l'affiche originale. Mais pour clarifier, le fichier requirements.txt de la branche intermédiaire peut contenir "-r requirements / staging.txt" (ou similaire), tandis que celui de la branche prod peut contenir "-r requirements / prod.txt" (voir la fin de ma réponse). Synchronisez la branche appropriée avec son instance Heroku correspondante.
Christian Abbott
2
@SohamNavadiya Ce n'est pas ce que j'ai demandé. Disons que j'ai un base.txtavec 3 paquets dedans, et dev.txtavec 1 paquet dedans (et -r base.txt). TOUS les 4 packages sont installés dans mon environnement virtuel. Je veux maintenant installer le 5ème paquet et le lister dans la base, PAS dans le développement, comment faire? Bien sûr, je peux l'installer et pip freeze > base.txtcela ne résout PAS le problème. Il met alors la 4ème dépendance dev en base dont je ne veux pas.
Manan Mehta
11

Une option viable aujourd'hui qui n'existait pas lorsque la question et la réponse d'origine ont été publiées est d'utiliser pipenv au lieu de pip pour gérer les dépendances.

Avec pipenv, la gestion manuelle de deux fichiers d'exigences distincts comme avec pip n'est plus nécessaire, mais pipenv gère lui-même les packages de développement et de production via des interactions sur la ligne de commande.

Pour installer un package à utiliser à la fois en production et en développement:

pipenv install <package>

Pour installer un package pour l'environnement de développement uniquement:

pipenv install <package> --dev

Via ces commandes, pipenv stocke et gère la configuration de l'environnement dans deux fichiers (Pipfile et Pipfile.lock). Le buildpack Python actuel de Heroku prend en charge nativement pipenv et se configurera à partir de Pipfile.lock s'il existe au lieu de requirements.txt.

Voir le lien pipenv pour une documentation complète de l'outil.

Christian Abbott
la source
4
pipenv est une perte de temps. Le verrouillage prend trop de temps.
nurettin
10
pipenv est cassé à presque tous les aspects. Il promet beaucoup, mais expédié très peu
ospider
5
@ospider J'utilise pipenv quotidiennement et je ne rencontre pas de problèmes aussi négatifs que vous et nurettin rapportez. Travailler avec la version pipenv 2018.10.13. Brisé sous tous ses aspects est donc une déclaration très vide.
Kwuite
1
@Kwuite Je partage le sentiment de votre dernière phrase. Il y a peu de dialogue à engager lorsqu'un commentaire est critique mais vide.
Christian Abbott
3
D'accord avec nurettin et ospider. pipenv est horrible.
Andrew Palmer
3

Si votre besoin est de pouvoir basculer entre les environnements sur la même machine, il peut être nécessaire de créer différents dossiers virtualenv pour chaque environnement vers lequel vous devez basculer.

python3 -m venv venv_dev
source venv_dev/bin/activate
pip install -r pip/common.txt
pip install -r pip/dev.txt
exit
python3 -m venv venv_prod
source venv_prod/bin/activate
pip install -r pip/common.txt
exit
source venv_dev/bin/activate
# now we are in dev environment so your code editor and build systems will work.

# let's install a new dev package:
# pip install awesome
# pip freeze -r pip/temp.txt
# find that package, put it into pip/dev.txt
# rm pip/temp.txt

# pretty cumbersome, but it works. 
Nurettin
la source