Déterminez si Python s'exécute dans virtualenv

272

Est-il possible de déterminer si le script actuel s'exécute dans un environnement virtualenv?

miracle2k
la source
2
Par curiosité, pourquoi voudriez-vous le savoir?
Jorge Leitao
1
c'est-à-dire pour pouvoir écrire un script personnalisé qui génère une invite pour votre shell et vous voulez que cette invite indique si vous êtes en venv ou non, donc vous voulez pouvoir détecter cela à partir de ce code, mieux sans appeler des outils externes .
Marcin Orlowski

Réponses:

227

AFAIK le moyen le plus fiable de vérifier cela (et la manière qui est utilisée en interne dans virtualenv et dans pip) est de vérifier l'existence de sys.real_prefix:

import sys

if hasattr(sys, 'real_prefix'):
    #...

À l'intérieur d'un virtualenv, sys.prefixpointe vers le répertoire virtualenv et sys.real_prefixpointe vers le "vrai" préfixe du système Python (souvent /usrou/usr/local ou quelque).

En dehors d'un virtualenv, sys.real_prefixne devrait pas exister.

L'utilisation de la VIRTUAL_ENVvariable d'environnement n'est pas fiable. Il est défini par le activatescript shell virtualenv , mais un virtualenv peut être utilisé sans activation en exécutant directement un exécutable à partir du répertoire virtualenv bin/(ou Scripts), auquel cas $VIRTUAL_ENVil ne sera pas défini.

Carl Meyer
la source
11
Cela ne semble plus être valable dans Python 3.
Dan P.
49
Si vous utilisez virtualenv (github.com/pypa/virtualenv), cette réponse est également correcte pour Python 2 ou Python 3. Si vous utilisez pyvenv ( legacy.python.org/dev/peps/pep-0405 ), virtualenv -équivalent intégré à Python 3.3+ (mais pas la même chose que virtualenv), alors il utilise sys.base_prefix au lieu de sys.real_prefix, et sys.base_prefix existe toujours; en dehors d'un pyvenv, il est égal à sys.prefix.
Carl Meyer
2
@Kounavi Je ne pense pas qu'il soit probable que la version Windows ait un impact. Cette réponse est au cœur du fonctionnement de virtualenv sur n'importe quelle plate-forme. Est-il possible que vous utilisiez Python 3 pyvenv, et non virtualenv, sur la machine Windows 2012? Ou que quelque chose se passe avec le PATH et que vous ne courez pas dans virtualenv quand vous pensez que vous l'êtes?
Carl Meyer
3
One-liner pour les scripts bashPYTHON_ENV=$(python -c "import sys; sys.stdout.write('1') if hasattr(sys, 'real_prefix') else sys.stdout.write('0')")
Sam Myers
2
Cette réponse est obsolète, sans surprise. Plus précisément, cette réponse renvoie des faux négatifs pour les cas d'utilisation courants. C'est mauvais. Au lieu de cela, voir soit: hroncok est mise à jour faisant autorité détecter correctement tous les non-Anaconda VENVS ou Victoria Stuart 's réponse faisant autorité détecter correctement tous Anaconda VENVS . ( Tous mes votes positifs pour celui qui combine ces deux réponses. )
Cecil Curry
98

Essayez d'utiliser pip -V(notez la majuscule V)

Si vous exécutez l'environnement virtuel. il montrera le chemin vers l'emplacement de l'env.

loki l
la source
Si vous vous êtes beaucoup déplacé virtualenv, il est possible que cela vous échoue ou vous mente. S'il ment, vous pouvez le faire find /path/to/venv/ -type f -exec sed -ie "s:/old/path/to/venv:/path/to/venv:g" {} \+. Si cela échoue (j'ai "de mauvaises données de marshal"), vous devrez effacer les fichiers .pyc avec find /path/to/venv -type f -name "*.pyc" -exec rm {} \+(ne vous inquiétez pas, ils se reconstruiront automatiquement).
jeremysprofile
Je viens de tester cela sur Windows 10 avec Python 3.7. Il imprime l'emplacement de pip à partir de l'installation par défaut ...\lib\site-packagesdans le %PATH%. Il retournera donc un faux positif dans ce cas.
JamesThomasMoon1979
72

Il s'agit d'une amélioration de la réponse acceptée par Carl Meyer . Il fonctionne avec virtualenv pour Python 3 et 2 et également pour le module venv dans Python 3:

import sys


def is_venv():
    return (hasattr(sys, 'real_prefix') or
            (hasattr(sys, 'base_prefix') and sys.base_prefix != sys.prefix))

La vérification des sys.real_prefixcouvertures virtualenv, l'égalité des non-vides sys.base_prefixavec les sys.prefixcouvertures venv.

Considérez un script qui utilise la fonction comme ceci:

if is_venv():
    print('inside virtualenv or venv')
else:
    print('outside virtualenv or venv')

Et l'invocation suivante:

$ python2 test.py 
outside virtualenv or venv

$ python3 test.py 
outside virtualenv or venv

$ python2 -m virtualenv virtualenv2
...
$ . virtualenv2/bin/activate
(virtualenv2) $ python test.py 
inside virtualenv or venv
(virtualenv2) $ deactivate

$ python3 -m virtualenv virtualenv3
...
$ . virtualenv3/bin/activate
(virtualenv3) $ python test.py 
inside virtualenv or venv
(virtualenv3) $ deactivate 

$ python3 -m venv venv3
$ . venv3/bin/activate
(venv3) $ python test.py 
inside virtualenv or venv
(venv3) $ deactivate 
hroncok
la source
4
Depuis Python 3.3 est plus maintenu ou pris en charge par la plupart des cadres Python 3 et applications, cette fonction réduit désormais à un trivial en une ligne: def is_venv(): return hasattr(sys, 'real_prefix') or sys.base_prefix != sys.prefix. Je dis juste.
Cecil Curry
Malheureusement, cela ne semble pas fonctionner avec pipenvles environnements virtuels créés.
dragon788
46

Vérifiez la $VIRTUAL_ENVvariable d'environnement.

La $VIRTUAL_ENVvariable d'environnement contient le répertoire de l'environnement virtuel dans un environnement virtuel actif.

>>> import os
>>> os.environ['VIRTUAL_ENV']
'/some/path/project/venv'

Une fois que vous exécutez deactivate/ quittez l'environnement virtuel, la $VIRTUAL_ENVvariable sera effacée / vide. Python lèvera un KeyErrorcar la variable d'environnement n'a pas été définie.

>>> import os
>>> os.environ['VIRTUAL_ENV']
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/Cellar/python/3.7.3/Frameworks/Python.framework/Versions/3.7/lib/python3.7/os.py", line 678, in __getitem__
    raise KeyError(key) from None
KeyError: 'VIRTUAL_ENV'

Ces mêmes vérifications de variables d'environnement peuvent bien sûr également être effectuées en dehors du script Python, dans le shell.

MrHetii
la source
1
Cela fonctionne à la fois pour un virtualenvvirtualenv et un venvvirtualenv.
florisla
@verboze: comme il est censé le faire, non? Un virtualenv désactivé signifie que le script utilisateur ne s'exécute pas sur un seul.
MestreLion
Cela vérifie si un virtualenv est activé, mais cela ne signifie pas nécessairement que le processus Python en cours d'exécution provient de ce virtualenv.
erb
20

Selon le pep virtualenv sur http://www.python.org/dev/peps/pep-0405/#specification, vous pouvez simplement utiliser sys.prefix à la place os.environ ['VIRTUAL_ENV'].

le sys.real_prefix n'existe pas dans mon virtualenv et pareil avec sys.base_prefix.

chronossc
la source
8
virtualenv est le projet autonome qui fonctionne sur n'importe quelle version de Python ( github.com/pypa/virtualenv ). Le PEP auquel vous avez lié est pour pyvenv, qui est basé sur virtualenv mais est implémenté différemment (mieux) et est intégré à Python 3.3+. Cette question concerne virtualenv, pas pyvenv. Vous avez raison, il n'y a pas de pyvenv sys.real_prefix.
Carl Meyer
5
Une bonne façon de détecter à partir de bash en utilisant cette réponse est de lancer: env |grep VIRTUAL_ENV |wc -l qui retournera un 1 si dans un venv ou un 0 sinon.
LISTERINE
3
Si vous êtes dans un shell, vous pouvez simplement utiliser [[ -n $VIRTUAL_ENV ]] && echo virtualenvou [[ -z $VIRTUAL_ENV ]] && echo not virtualenvselon vos besoins.
Six
10

Pour vérifier si votre Virtualenv intérieur:

import os

if os.getenv('VIRTUAL_ENV'):
    print('Using Virtualenv')
else:
    print('Not using Virtualenv')

Vous pouvez également obtenir plus de données sur votre environnement:

import sys
import os

print(f'Python Executable: {sys.executable}')
print(f'Python Version: {sys.version}')
print(f'Virtualenv: {os.getenv("VIRTUAL_ENV")}')
Matt Harasymczuk
la source
1
Il s'agit de la meilleure approche multiplateforme (Windows / Unix).
Adi Unnithan
Jusqu'à présent, ce n'est que multiplateforme, compatible avec python 2 et python 3. Merci.
RJ
9

Il y a plusieurs bonnes réponses ici, et certaines moins robustes. Voici un aperçu.

Comment ne pas le faire

Ne vous fiez pas à l'emplacement de Python ou site-packages dossier.

Si ceux-ci sont définis sur des emplacements non standard, cela ne signifie pas que vous êtes réellement dans un environnement virtuel. Les utilisateurs peuvent avoir plus d'une version Python installée, et ce n'est pas toujours là où vous vous attendez.

Évitez de regarder:

  • sys.executable
  • sys.prefix
  • pip -V
  • which python

En outre, ne vérifie pas la présence de venv, .venvou envsdans l' un de ces chemins. Cela se cassera pour les environnements avec un emplacement plus unique. Par exemple, Pipenv utilise des valeurs de hachage comme nom pour ses environnements.

VIRTUAL_ENV variable d'environnement

Les deux virtualenvet venvdéfinissent la variable d'environnement $VIRTUAL_ENVlors de l'activation d'un environnement. Voir PEP 405 .

Vous pouvez lire cette variable dans des scripts shell ou utiliser ce code Python pour déterminer si elle est définie.

import os
running_in_virtualenv = "VIRTUAL_ENV" in os.environ

# alternative ways to write this, also supporting the case where
# the variable is set but contains an empty string to indicate
# 'not in a virtual environment':
running_in_virtualenv = bool(os.environ.get("VIRTUAL_ENV"))
running_in_virtualenv = bool(os.getenv("VIRTUAL_ENV"))

Le problème est que cela ne fonctionne que lorsque l'environnement est activé par le activatescript shell.

Vous pouvez démarrer les scripts de l'environnement sans activer l'environnement , donc si c'est un problème, vous devez utiliser une méthode différente.

sys.base_prefix

virtualenv, venvEt le pyvenvpoint sys.prefixà Python installé à l' intérieur de l'virtualenv que vous attendez.

Dans le même temps, la valeur d' origine de sys.prefixest également disponible en tant que sys.base_prefix.

Nous pouvons l'utiliser pour détecter si nous sommes dans un virtualenv.

import sys
# note: Python versions before 3.3 don't have sys.base_prefix
# if you're not in virtual environment
running_in_virtualenv = sys.prefix != sys.base_prefix

Se retirer: sys.real_prefix

Attention maintenant, virtualenvavant que la version 20 ne soit pas définie, sys.base_prefixmais elle est définie à la sys.real_prefixplace.

Donc, pour être sûr, vérifiez les deux comme suggéré dans la réponse de hroncok :

import sys

real_prefix = getattr(sys, "real_prefix", None)
base_prefix = getattr(sys, "base_prefix", sys.prefix)

running_in_virtualenv = (base_prefix or real_prefix) != sys.prefix

Anaconda

Si vous utilisez des environnements virtuels Anaconda, vérifiez la réponse de Victoria Stuart .

florisla
la source
Le PO demande "Comment faire?", Pas "Comment NE PAS?" Cette réponse est exagérée. Cela dépasse l'esprit de la question et obscurcit la réponse avec trop de variations. Veuillez garder vos réponses aussi simples que possible et répondre directement à la question.
Rich Lysakowski PhD
Je résume ici les multiples réponses et donne des conseils sur celle qui pourrait convenir à des circonstances spécifiques. La question d'origine ne fournit pas suffisamment de contexte pour sélectionner l'une de ces techniques comme la «meilleure» - ce n'est tout simplement pas si simple.
florisla
1
Dans la section pour sys.base_prefix, le test ne devrait-il pas être:running_in_virtualenv = sys.*base_*prefix != sys.prefix
usonianhorizon
@usonianhorizon C'est vrai, merci!
florisla
Merci, @florisia! Je suis en train de passer de virtualenvwrapper au venv intégré pour le déploiement d'applications, et votre explication m'a donné le modèle sur la façon de le faire. Je ne comptais que sur le if hasattr(sys, 'real_prefix'):test, qui ne fonctionnait plus.
usonianhorizon
8

Vous pouvez faire which pythonet voir si son pointage vers celui dans env virtuel.

kunrazor
la source
1
whichn'est pas disponible par défaut sous Windows. Vous pouvez utiliser à la whereplace sur Windows ou utiliser quel artisanat . Ou regardez sys.executable. Mais encore, il existe de meilleures méthodes.
florisla
5
  • Mis à jour en novembre 2019 (en annexe).

J'utilise régulièrement plusieurs environnements virtuels installés par Anaconda (venv). Cet extrait de code / exemples vous permet de déterminer si vous êtes ou non dans un venv (ou votre environnement système), et d'exiger également un venv spécifique pour votre script.

Ajouter au script Python (extrait de code):

# ----------------------------------------------------------------------------
# Want script to run in Python 3.5 (has required installed OpenCV, imutils, ... packages):
import os

# First, see if we are in a conda venv { py27: Python 2.7 | py35: Python 3.5 | tf: TensorFlow | thee : Theano }
try:
   os.environ["CONDA_DEFAULT_ENV"]
except KeyError:
   print("\tPlease set the py35 { p3 | Python 3.5 } environment!\n")
   exit()

# If we are in a conda venv, require the p3 venv:
if os.environ['CONDA_DEFAULT_ENV'] != "py35":
    print("\tPlease set the py35 { p3 | Python 3.5 } environment!\n")
    exit()

# See also:
# Python: Determine if running inside virtualenv
# http://stackoverflow.com/questions/1871549/python-determine-if-running-inside-virtualenv  
# [ ... SNIP! ... ]

Exemple:

$ p2
  [Anaconda Python 2.7 venv (source activate py27)]

(py27) $ python  webcam_.py
    Please set the py35 { p3 | Python 3.5 } environment!

(py27) $ p3
  [Anaconda Python 3.5 venv (source activate py35)]

(py35) $ python  webcam.py -n50

    current env: py35
    processing (live): found 2 faces and 4 eyes in this frame
    threaded OpenCV implementation
    num_frames: 50
    webcam -- approx. FPS: 18.59
    Found 2 faces and 4 eyes!
(py35) $

Mise à jour 1 - utilisation dans les scripts bash:

Vous pouvez également utiliser cette approche dans les scripts bash (par exemple, ceux qui doivent s'exécuter dans un environnement virtuel spécifique). Exemple (ajouté au script bash):

if [ $CONDA_DEFAULT_ENV ]        ## << note the spaces (important in BASH)!
    then
        printf 'venv: operating in tf-env, proceed ...'
    else
        printf 'Note: must run this script in tf-env venv'
        exit
fi

Mise à jour 2 [novembre 2019]

Depuis mon article d'origine, je suis passé d'Anaconda venv (et Python lui-même a évolué dans des environnements virtuels à savoir ).

En réexaminant ce problème, voici du code Python mis à jour que vous pouvez insérer pour tester que vous travaillez dans un environnement virtuel Python spécifique (venv).

import os, re
try:
    if re.search('py37', os.environ['VIRTUAL_ENV']):
        pass
except KeyError:
    print("\n\tPlease set the Python3 venv [alias: p3]!\n")
    exit()

Voici un code explicatif.

[victoria@victoria ~]$ date; python --version
  Thu 14 Nov 2019 11:27:02 AM PST
  Python 3.8.0

[victoria@victoria ~]$ python
  Python 3.8.0 (default, Oct 23 2019, 18:51:26) 
  [GCC 9.2.0] on linux
  Type "help", "copyright", "credits" or "license" for more information.

>>> import os, re

>>> re.search('py37', os.environ['VIRTUAL_ENV'])
<re.Match object; span=(20, 24), match='py37'>

>>> try:
...     if re.search('py37', os.environ['VIRTUAL_ENV']):
...       print('\n\tOperating in Python3 venv, please proceed!  :-)')
... except KeyError:
...     print("\n\tPlease set the Python3 venv [alias: p3]!\n")
... 

    Please set the Python3 venv [alias: p3]!

>>> [Ctrl-d]
  now exiting EditableBufferInteractiveConsole...

[victoria@victoria ~]$ p3
  [Python 3.7 venv (source activate py37)]

(py37) [victoria@victoria ~]$ python --version
  Python 3.8.0

(py37) [victoria@victoria ~]$ env | grep -i virtual
  VIRTUAL_ENV=/home/victoria/venv/py37

(py37) [victoria@victoria ~]$ python
  Python 3.8.0 (default, Oct 23 2019, 18:51:26) 
  [GCC 9.2.0] on linux
  Type "help", "copyright", "credits" or "license" for more information.

>>> import os, re
>>> try:
...     if re.search('py37', os.environ['VIRTUAL_ENV']):
...       print('\n\tOperating in Python3 venv, please proceed!  :-)')
... except KeyError:
...     print("\n\tPlease set the Python3 venv [alias: p3]!\n")
... 

    Operating in Python3 venv, please proceed!  :-)
>>> 
Victoria Stuart
la source
3

Le moyen le plus simple est de simplement lancer: which pythonsi vous êtes dans un virtualenv, il pointera vers son python au lieu du global

Silvio Biasiol
la source
1
Je ne pense pas que cela réponde réellement à la question (qui est préoccupée par le "script actuel"). Cependant, cela répond à ma question particulière, "comment savoir si je suis dans un environnement virtuel à partir de la ligne de commande."
ukrutt
1

(édité) J'ai trouvé ça, qu'en pensez-vous? (il retourne également le chemin de base de venv et fonctionne même pour les documents de lecture où la vérification de la variable env ne fonctionne pas):

import os
import sys
from distutils.sysconfig import get_config_vars


def get_venv_basedir():
    """Returns the base directory of the virtualenv, useful to read configuration and plugins"""

    exec_prefix = get_config_vars()['exec_prefix']

    if hasattr(sys, 'real_prefix') is False or exec_prefix.startswith(sys.real_prefix):
        raise EnvironmentError('You must be in a virtual environment')

    return os.path.abspath(get_config_vars()['exec_prefix'] + '/../')

la source
0

Il y a déjà beaucoup de bonnes méthodes publiées ici, mais en ajoutant juste une de plus:

import site
site.getsitepackages()

vous indique où sont pipinstallés les packages.

flow2k
la source
Cela ne dit pas si Python s'exécute dans un environnement virtuel ou non.
florisla
@florisla Pourriez-vous élaborer? Si site.getsitepackages()génère un répertoire qui n'est pas celui du système, vous pouvez en déduire que vous êtes dans un environnement virtuel.
flow2k
Vous pouvez installer Python à plusieurs emplacements. Par exemple, sous Windows, vous pouvez installer un Python «système» et une distribution WinPython plus un Python basé sur Conda. Ils ont tous des dossiers de packages de site différents mais ne sont pas nécessairement créés par (ou utilisés dans) a virtualenv.
florisla
@florisla Bon point - je viens de voir que (venv ou pas) est ce que la question pose (j'avais écrit une réponse similaire pour une autre question). Je suis d'accord que cela pourrait ne pas donner la réponse infaillible quant à savoir si vous êtes dans un venv ou non, mais pourrait aider à vous dire quel Python ou lequel venvvous utilisez.
flow2k
-1

Ce n'est pas à l'épreuve des balles mais pour les environnements UNIX, test simple comme

if run("which python3").find("venv") == -1:
    # something when not executed from venv

fonctionne très bien pour moi. C'est plus simple que de tester un attribut existant et, de toute façon, vous devez nommer votre répertoire venvvenv .

Mat
la source
-1

Dans Windows OS, vous voyez quelque chose comme ceci:

C:\Users\yourusername\virtualEnvName\Scripts>activate
(virtualEnvName) C:\Users\yourusername\virtualEnvName\Scripts>

Les parenthèses signifient que vous êtes réellement dans l'environnement virtuel appelé "virtualEnvName".

getleft
la source
Vous et moi pouvons très bien lire «virtualEnvName». Mais la question est de savoir comment un module Python peut lire ceci.
florisla
-1

Une solution potentielle est:

os.access(sys.executable, os.W_OK)

Dans mon cas, je voulais juste détecter si je pouvais installer des éléments avec pip tel quel. Bien que ce ne soit pas la bonne solution dans tous les cas, pensez simplement à vérifier si vous avez des autorisations d'écriture pour l'emplacement de l'exécutable Python.

Remarque: cela fonctionne dans toutes les versions de Python, mais renvoie également Truesi vous exécutez le système Python avec sudo. Voici un cas d'utilisation potentiel:

import os, sys
can_install_pip_packages = os.access(sys.executable, os.W_OK)

if can_install_pip_packages:
    import pip
    pip.main(['install', 'mypackage'])
Matthew D. Scholefield
la source
-1

C'est une vieille question, mais trop d'exemples ci-dessus sont trop compliqués.

Keep It Simple: (dans Jupyter Notebook ou le terminal Python 3.7.1 sur Windows 10)


import sys
print(sys.executable)```

# example output: >> `C:\Anaconda3\envs\quantecon\python.exe`

OR 
```sys.base_prefix```

# Example output: >> 'C:\\Anaconda3\\envs\\quantecon'
Rich Lysakowski PhD
la source
Si vous ajoutez une logique pour vérifier la présence de envsdans ce chemin, cela cessera de fonctionner lorsque vous passerez d’anaconda à virtualenvou pipenv.
florisla
Florisla, vous avez fourni votre réponse "Comment ne pas le faire" près de 3 mois après avoir fourni une réponse qui fonctionne pour moi dans certaines limites (je ne passe pas de virtualenv à pipenv). C'est un mauvais sport de sous-évaluer les réponses des autres pour améliorer votre apparence.
Rich Lysakowski PhD
Rich, ce qui fonctionne pour vous peut ne pas fonctionner pour d'autres personnes. Cela peut même ne pas fonctionner pour l'affiche originale.
florisla