Est-il mauvais d'avoir mon répertoire virtualenv dans mon référentiel git?

285

Je pense à mettre le virtualenv pour une application web Django que je crée dans mon référentiel git pour l'application. Cela semble être un moyen facile de maintenir le déploiement simple et facile. Y a-t-il une raison pour laquelle je ne devrais pas faire cela?

Lyle Pratt
la source

Réponses:

302

J'utilise pip freezepour obtenir les packages dont j'ai besoin dans un requirements.txtfichier et les ajouter à mon référentiel. J'ai essayé de penser à un moyen pour lequel vous voudriez stocker l'intégralité du virtualenv, mais je n'ai pas pu.

RyanBrady
la source
81
Vous pouvez économiser l'espace inutile dans votre référentiel et toujours déployer sur un nouveau serveur en une seule commande: virtualenv --no-site-packages --distribute .env && source .env / bin / activate && pip install -r requirements.txt
RyanBrady
2
Je vous donne la réponse à cette question, car c'est probablement la "meilleure pratique" et vous l'avez proposée en premier. J'ai certainement rencontré certains des problèmes que tout le monde a mentionnés. J'estime que je me donne un autre jour à jouer avec ça avant de faire ce que vous avez toujours suggéré et d'utiliser pip et un fichier d'exigences. Merci de votre aide!
Lyle Pratt
11
Si vous, par exemple pip install mysql-python, sur une machine 64 bits, puis que quelqu'un avec une machine 32 bits essaie de l'utiliser, cela ne fonctionnera pas. Il utilise un module C, comme le font de nombreux modules Python, pour augmenter les performances. J'imagine que Windows-> Linux ne fonctionnerait pas non plus.
Matt Williamson
7
juste une remarque: nous nous sommes mordus dans le passé parce que les bibliothèques deviennent indisponibles depuis pip (version trop ancienne), forçant une mise à jour pendant que le site était en panne. alors ... je ne compterai plus jamais pip freezepour le faire. le problème est que pendant votre redéploiement forcé de mise à niveau, personne ne paie pour cela, et pour les mises à niveau intermédiaires (maintenance «best practice»), personne ne le fait non plus.
LE CONTRAT DIT QUE J'AI DROIT
5
Remarque sur le commentaire @RayanBrady: Les options --distributeet --setuptoolssont désormais sans effet. (Distribuer, c'était une fourchette de setuptools a été fusionné il y a longtemps). --no-site-packagesest obsolète, c'est maintenant le comportement par défaut
JackNova
49

Le stockage du répertoire virtualenv dans git vous permettra, comme vous l'avez noté, de déployer toute l'application en faisant simplement un clone git (plus l'installation et la configuration d'Apache / mod_wsgi). Un problème potentiellement important avec cette approche est que sous Linux, le chemin complet est codé en dur dans les scripts activate, django-admin.py, easy_install et pip de venv. Cela signifie que votre virtualenv ne fonctionnera pas entièrement si vous souhaitez utiliser un chemin différent, peut-être pour exécuter plusieurs hôtes virtuels sur le même serveur. Je pense que le site Web peut fonctionner avec les mauvais chemins dans ces fichiers, mais vous rencontrerez des problèmes la prochaine fois que vous essayerez d'exécuter pip.

La solution, déjà donnée, consiste à stocker suffisamment d'informations dans git pour que, pendant le déploiement, vous puissiez créer le virtualenv et effectuer les installations pip nécessaires. Généralement, les gens courent pip freezepour obtenir la liste, puis la stockent dans un fichier nommé requirements.txt. Il peut être chargé avec pip install -r requirements.txt. RyanBrady a déjà montré comment vous pouvez enchaîner les instructions de déploiement sur une seule ligne:

# before 15.1.0
virtualenv --no-site-packages --distribute .env &&\
    source .env/bin/activate &&\
    pip install -r requirements.txt

# after deprecation of some arguments in 15.1.0
virtualenv .env && source .env/bin/activate && pip install -r requirements.txt

Personnellement, je viens de les mettre dans un script shell que je lance après avoir fait le git clone ou git pull.

Le stockage du répertoire virtualenv facilite également la gestion des mises à niveau pip, car vous devrez ajouter / supprimer et valider manuellement les fichiers résultant de la mise à niveau. Avec un fichier requirements.txt, il vous suffit de modifier les lignes appropriées dans requirements.txt et de réexécuter pip install -r requirements.txt. Comme déjà indiqué, cela réduit également le "commit spam".

David Sickmiller
la source
4
Notez que --distribute est désormais obsolète (au moins dans 15.1.0): --distribute DEPRECATED. Retained only for backward compatibility. This option has no effect.
AnthonyC
1
--no-site-packagesest également déconseillé dans la version 15.1.0, car c'est désormais la valeur par défaut.
cjs
35

J'avais l'habitude de faire la même chose jusqu'à ce que je commence à utiliser des bibliothèques qui sont compilées différemment selon l'environnement tel que PyCrypto. Mon mac PyCrypto ne fonctionnerait pas sur Cygwin ne fonctionnerait pas sur Ubuntu.

Cela devient un véritable cauchemar pour gérer le référentiel.

Quoi qu'il en soit, j'ai trouvé plus facile de gérer le pip pipeze et un fichier d'exigences que de tout avoir dans git. C'est aussi plus propre car vous évitez le spam de validation pour des milliers de fichiers lorsque ces bibliothèques sont mises à jour ...

Yuji 'Tomita' Tomita
la source
Hmm. Je n'aurai certainement pas de problèmes avec les choses qui sont compilées différemment dans différents environnements. Je suppose que cela vaut probablement la peine de ne pas le faire juste pour éviter le spam de commit.
Lyle Pratt
@LylePratt: Je pense le contraire: mieux vaut ne pas inclure virtualenv entier dans le référentiel juste pour éviter des problèmes avec des outils aussi performants que PyCrypto ou PIL.
Tadeck
17

Je pense que l'un des principaux problèmes qui se posent est que le virtualenv pourrait ne pas être utilisable par d'autres personnes. La raison en est qu'il utilise toujours des chemins absolus. Donc, si vous virtualenv était par exemple en/home/lyle/myenv/ dedans, il assumera la même chose pour toutes les autres personnes utilisant ce référentiel (il doit être exactement le même chemin absolu). Vous ne pouvez pas présumer que des personnes utilisent la même structure de répertoires que vous.

La meilleure pratique est que chacun installe son propre environnement (que ce soit avec ou sans virtualenv) et y installe des bibliothèques. Cela rend également le code plus utilisable sur différentes plates-formes (Linux / Windows / Mac), également parce que virtualenv est installé différemment dans chacune d'elles.

Torsten Engelbrecht
la source
C'est juste pourquoi il est une mauvaise idée de conserver un virtualenv dans SCM, mais cela vaut la peine d'envisager quelque chose comme la suggestion de @ RJBrady ou un événement un script bootstrap.py , car avoir un moyen de recréer le même environnement sur plusieurs machines est un besoin sérieux lorsque vous travaillez avec d'autres personnes.
ig0774
Je ne suis pas vraiment sûr que le problème que vous avez mentionné soit exactement un problème dans ma situation. Mon application Django contient un fichier .wsgi qui définit où se trouve virtualenv par rapport à son emplacement (2 répertoires vers le haut '../../env'). Donc, dans mon scénario, le problème de chemin absolu ne devrait pas me nuire ... non?
Lyle Pratt
Si vous exécutez votre application toujours avec WSGI, vous pourriez vous en sortir. Si vous utilisez le serveur de développement (via manage.py), vous rencontrerez certainement des problèmes.
Torsten Engelbrecht
3

J'utilise ce qui est fondamentalement la réponse de David Sickmiller avec un peu plus d'automatisation. Je crée un fichier (non exécutable) au niveau supérieur de mon projet nommé activateavec le contenu suivant:

[ -n "$BASH_SOURCE" ] \
    || { echo 1>&2 "source (.) this with Bash."; exit 2; }
(
    cd "$(dirname "$BASH_SOURCE")"
    [ -d .build/virtualenv ] || {
        virtualenv .build/virtualenv
        . .build/virtualenv/bin/activate
        pip install -r requirements.txt
    }
)
. "$(dirname "$BASH_SOURCE")/.build/virtualenv/bin/activate"

(Selon la réponse de David, cela suppose que vous faites un pip freeze > requirements.txtpour maintenir à jour votre liste d'exigences.)

Ce qui précède donne l'idée générale; le script d' activation ( documentation ) que j'utilise normalement est un peu plus sophistiqué, offrant une -qoption (silencieuse), utilisant pythonquandpython3 n'est pas disponible, etc.

Celui-ci peut alors provenir de n'importe quel répertoire de travail actuel et s'activera correctement, en configurant d'abord l'environnement virtuel si nécessaire. Mon script de test de niveau supérieur contient généralement du code dans ce sens afin qu'il puisse être exécuté sans que le développeur n'ait à l'activer en premier:

cd "$(dirname "$0")"
[[ $VIRTUAL_ENV = $(pwd -P) ]] || . ./activate

L'approvisionnement ./activate, non activate, est important ici car ce dernier en trouvera un autre activatesur votre chemin avant de trouver celui du répertoire courant.

cjs
la source
Aimer cette approche! Cela semble très raisonnable, merci du partage.
Esolitos
J'ai dû changer la première ligne pour [[ $_ != $0 ]] || { echo 1>&2 "source (.) this script with Bash."; exit 2; }détecter si le script était en cours d'exécution par opposition à celui d'origine
Chris Snow
3

Ce n'est pas une bonne idée d'inclure un composant ou un paramètre dépendant de l'environnement dans votre référentiel comme l'un des aspects clés de l'utilisation d'un référentiel, c'est peut-être de le partager avec d'autres développeurs. Voici comment je configurerais mon environnement de développement sur un PC Windows (disons, Win10).

  1. Ouvrez Pycharm et sur la première page, choisissez de vérifier le projet à partir de votre système de contrôle de source (dans mon cas, j'utilise github)

  2. Dans Pycharm, accédez aux paramètres et choisissez "Project Interpreter" et choisissez l'option pour ajouter un nouvel environnement virtuel, vous pouvez l'appeler "venv".

  3. Choisissez l'interpréteur python de base qui se trouve dans C: \ Users {user} \ AppData \ Local \ Programs \ Python \ Python36 (assurez-vous de choisir la version appropriée de Python en fonction de ce que vous avez installé)

  4. Notez que Pycharm créera le nouvel environnement virtuel et copiera les binaires python et les bibliothèques requises sous votre dossier venv dans votre dossier de projet.

  5. Laissez Pycharm achever sa numérisation car elle a besoin de reconstruire / rafraîchir le squelette de votre projet

  6. exclure le dossier venv de vos interactions git (ajoutez venv \ au fichier .gitignore dans votre dossier de projet)

Bonus: si vous voulez que les gens installent facilement (enfin, presque facilement) toutes les bibliothèques dont votre logiciel a besoin, vous pouvez utiliser

pip freeze > requirements.txt

et mettez les instructions sur votre git pour que les gens puissent utiliser la commande suivante pour télécharger toutes les bibliothèques requises en même temps.

pip install -r requirements.txt 
William Pourmajidi
la source
2

Si vous savez sur quels systèmes d'exploitation votre application sera exécutée, je créerais un virtualenv pour chaque système et l'inclurais dans mon référentiel. Ensuite, je ferais en sorte que mon application détecte le système sur lequel elle s'exécute et utilise le virtualenv correspondant.

Le système pourrait par exemple être identifié à l'aide du module de plateforme .

En fait, c'est ce que je fais avec une application interne que j'ai écrite et à laquelle je peux rapidement ajouter virtualenv d'un nouveau système au cas où cela serait nécessaire. De cette façon, je n'ai pas à compter sur le fait que pip sera en mesure de télécharger avec succès le logiciel dont mon application a besoin. Je n'aurai pas non plus à me soucier de la compilation de psycopg2 par exemple que j'utilise.

Si vous ne savez pas sur quel système d'exploitation votre application peut s'exécuter, il vaut probablement mieux utiliser pip freezecomme suggéré dans d'autres réponses ici.

Fredrik
la source
0

Je pense que le mieux est d'installer l'environnement virtuel dans un chemin à l'intérieur du dossier du référentiel, peut-être est-il préférable d'inclure un sous-répertoire dédié à l'environnement (j'ai supprimé accidentellement tout mon projet lorsque je force l'installation d'un environnement virtuel dans la racine du référentiel dossier, bon que j'avais le projet enregistré dans sa dernière version dans Github).

Le programme d'installation automatisé ou la documentation doit indiquer le chemin virtualenv en tant que chemin relatif, de cette façon vous ne rencontrerez pas de problèmes lors du partage du projet avec d'autres personnes. À propos des packages, les packages utilisés doivent être enregistrés par pip freeze -r requirements.txt.

Lucioric2000
la source
-1

Si vous configurez simplement le développement env, utilisez le fichier de gel pip, caz qui rend le repo git propre.

Ensuite, si vous effectuez un déploiement de production, archivez tout le dossier venv. Cela rendra votre déploiement plus reproductible, n'aura pas besoin de ces packages libxxx-dev et évitera les problèmes Internet.

Il y a donc deux repos. Un pour votre code source principal, qui comprend un fichier requirements.txt. Et un repo env, qui contient tout le dossier venv.

Shuo
la source