Determine si Python se está ejecutando dentro de virtualenv

272

¿Es posible determinar si el script actual se está ejecutando dentro de un entorno virtualenv?

miracle2k
fuente
2
Por curiosidad, ¿por qué quieres saber eso?
Jorge Leitao
1
es decir, para poder escribir un script personalizado que genere un aviso para su shell y desea que ese aviso indique si está en venv o no, por lo que desea poder detectar eso desde ese código, mejor sin llamar a herramientas externas .
Marcin Orlowski

Respuestas:

227

AFAIK la forma más confiable de verificar esto (y la forma en que se usa internamente en virtualenv y en pip) es verificar la existencia de sys.real_prefix:

import sys

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

Dentro de un virtualenv, sys.prefixapunta al directorio virtualenv, y sys.real_prefixapunta al prefijo "real" del sistema de Python (a menudo /usro /usr/localo algo así).

Fuera de un virtualenv, sys.real_prefixno debería existir.

Usar la VIRTUAL_ENVvariable de entorno no es confiable. Está configurado por el activatescript de shell virtualenv , pero un virtualenv puede usarse sin activación ejecutando directamente un ejecutable desde el directorio virtualenv bin/(o Scripts), en cuyo caso $VIRTUAL_ENVno se establecerá.

Carl Meyer
fuente
11
Esto ya no parece ser válido en Python 3.
Dan P.
49
Si está usando virtualenv (github.com/pypa/virtualenv), esta respuesta es igualmente correcta para Python 2 o Python 3. Si está usando pyvenv ( legacy.python.org/dev/peps/pep-0405 ), un virtualenv -equivalente integrado en Python 3.3+ (pero no es lo mismo que virtualenv), luego usa sys.base_prefix en lugar de sys.real_prefix, y sys.base_prefix siempre existe; fuera de pyvenv es igual a sys.prefix.
Carl Meyer
2
@ Kounavi No creo que sea probable que la versión de Windows tenga algún impacto. Esta respuesta es una parte central de cómo funciona virtualenv en cualquier plataforma. ¿Es posible que esté utilizando Python 3 pyvenv, no virtualenv, en la máquina con Windows 2012? ¿O que algo está sucediendo con el PATH y de hecho no estás corriendo en el virtualenv cuando crees que sí?
Carl Meyer
3
One-liner para guiones de bashPYTHON_ENV=$(python -c "import sys; sys.stdout.write('1') if hasattr(sys, 'real_prefix') else sys.stdout.write('0')")
Sam Myers
2
Esta respuesta es obsoleta, como era de esperar. Específicamente, esta respuesta devuelve falsos negativos para casos de uso comunes. Eso es malo. En su lugar, ya sea ver: hroncok 's actualización autorizada detectar correctamente todos los no-Anaconda venvs o Victoria Stuart ' s respuesta autorizada detectar correctamente todas Anaconda venvs . ( Todos mis votos a favor de quien combine esas dos respuestas. )
Cecil Curry
98

Intenta usar pip -V(nota mayúscula V)

Si está ejecutando el entorno virtual. mostrará el camino a la ubicación del entorno.

loki l
fuente
Si te has mudado virtualenvmucho, es posible que esto pueda fallar o mentirte. Si está mintiendo, puedes hacerlo find /path/to/venv/ -type f -exec sed -ie "s:/old/path/to/venv:/path/to/venv:g" {} \+. Si está fallando (obtuve "datos incorrectos del mariscal"), deberá borrar los archivos .pyc find /path/to/venv -type f -name "*.pyc" -exec rm {} \+(no se preocupe, se reconstruirán automáticamente).
jeremysprofile
Acabo de probar esto en Windows 10 con Python 3.7. Imprime la ubicación de pip desde la instalación predeterminada ...\lib\site-packagesen %PATH%. Entonces devolverá un falso positivo en ese caso.
JamesThomasMoon1979
72

Esta es una mejora de la respuesta aceptada por Carl Meyer . Funciona con virtualenv para Python 3 y 2 y también para el módulo venv en Python 3:

import sys


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

El cheque para sys.real_prefixcubiertas virtualenv, la igualdad de no vacías sys.base_prefixcon sys.prefixcubiertas venv.

Considere un script que usa la función de esta manera:

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

Y la siguiente invocación:

$ 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
fuente
44
Desde Python 3.3 ya no es mantenido o soportado por la mayoría de Python 3 marcos y aplicaciones, esta función reduce ahora a una sola línea trivial: def is_venv(): return hasattr(sys, 'real_prefix') or sys.base_prefix != sys.prefix. Sólo digo'.
Cecil Curry
Lamentablemente, esto no parece funcionar con pipenventornos virtuales creados.
dragon788
46

Verifique la $VIRTUAL_ENVvariable de entorno.

La $VIRTUAL_ENVvariable de entorno contiene el directorio del entorno virtual cuando se encuentra en un entorno virtual activo.

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

Una vez que ejecuta deactivate/ abandona el entorno virtual, la $VIRTUAL_ENVvariable se borrará / vaciará. Python generará un KeyErrorporque la variable de entorno no estaba configurada.

>>> 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'

Estas mismas comprobaciones de variables de entorno, por supuesto, también se pueden hacer fuera del script de Python, en el shell.

MrHetii
fuente
1
Esto funciona tanto para un virtualenvvirtualenv como para un venvvirtualenv.
florisla
@verboze: como se supone que debe hacer, ¿verdad? Un virtualenv desactivado significa que el script de usuario no se está ejecutando en uno.
MestreLion
Esto comprueba si un virtualenv está activado, pero eso no significa necesariamente que el proceso de Python en ejecución sea de ese virtualenv.
erb
20

De acuerdo con virtualenv pep en http://www.python.org/dev/peps/pep-0405/#specification , puede usar sys.prefix en lugar de os.environ ['VIRTUAL_ENV'].

sys.real_prefix no existe en mi virtualenv y lo mismo ocurre con sys.base_prefix.

cronossc
fuente
8
virtualenv es el proyecto independiente que funciona en cualquier versión de Python ( github.com/pypa/virtualenv ). El PEP al que se vinculó es para pyvenv, que se basa en virtualenv pero se implementa de manera diferente (mejor) y está integrado en Python 3.3+. Esta pregunta es sobre virtualenv, no pyvenv. Tienes razón en que en un pyvenv no hay sys.real_prefix.
Carl Meyer
55
Una buena manera de detectar desde bash usando esta respuesta es ejecutar: env |grep VIRTUAL_ENV |wc -l que devolverá un 1 si está en un venv o un 0 si no.
LISTERINE
3
Si está dentro de un caparazón, simplemente puede usarlo [[ -n $VIRTUAL_ENV ]] && echo virtualenvo [[ -z $VIRTUAL_ENV ]] && echo not virtualenvsegún sus necesidades.
Seis
10

Para verificar si está dentro de Virtualenv:

import os

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

También puede obtener más datos sobre su entorno:

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
fuente
1
Este es el mejor enfoque multiplataforma (Windows / Unix).
Adi Unnithan
Hasta ahora, esto es solo compatible con multiplataforma, python 2 y python 3. Gracias.
RJ
9

Aquí hay varias buenas respuestas, y algunas menos robustas. Aquí hay una descripción general.

Cómo no hacerlo

No confíe en la ubicación de Python o la site-packagescarpeta.

Si se configuran en ubicaciones no estándar, eso no significa que esté realmente en un entorno virtual. Los usuarios pueden tener más de una versión de Python instalada, y no siempre están donde espera que estén.

Evita mirar:

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

Además, no se verifique la presencia de venv, .venvo envsen cualquiera de estos caminos. Esto se romperá para entornos con una ubicación más única. Por ejemplo, Pipenv usa valores hash como nombre para sus entornos.

VIRTUAL_ENV Variable ambiental

Ambos virtualenvy venvestablecer la variable de entorno $VIRTUAL_ENVal activar un entorno. Ver PEP 405 .

Puede leer esta variable en scripts de shell o usar este código de Python para determinar si está configurado.

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"))

El problema es que esto sólo funciona cuando el ambiente se activa por el activatescript de shell.

Puede iniciar los scripts del entorno sin activar el entorno , por lo que si eso le preocupa, debe usar un método diferente.

sys.base_prefix

virtualenv, venvY el pyvenvpunto sys.prefixa la de Python instalado en el interior de la virtualenv como era de esperar.

Al mismo tiempo, el valor original de sys.prefixtambién está disponible como sys.base_prefix.

Podemos usar eso para detectar si estamos en 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

Retroceder: sys.real_prefix

Ahora tenga cuidado, virtualenvantes de que la versión 20 no se configurara, sys.base_prefixsino que se configuraba sys.real_prefix.

Entonces, para estar seguro, verifique ambos como se sugiere en la respuesta 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 está utilizando entornos virtuales Anaconda, verifique la respuesta de Victoria Stuart .

florisla
fuente
El OP pregunta "¿Cómo lo hago?", No "¿Cómo NO hacerlo?" Esta respuesta es exagerada. Va más allá del espíritu de la pregunta y ofusca la respuesta con demasiadas variaciones. Mantenga sus respuestas lo más simple posible y responda la pregunta directamente.
Rich Lysakowski PhD
Estoy resumiendo las múltiples respuestas aquí y brindando consejos sobre cuál podría ser la correcta para circunstancias específicas. La pregunta original no proporciona suficiente contexto para seleccionar una de estas técnicas como la 'mejor', simplemente no es tan simple.
florisla
1
En la sección de sys.base_prefix, ¿no debería ser la prueba:running_in_virtualenv = sys.*base_*prefix != sys.prefix
usonianhorizon
@usonianhorizon Cierto, gracias!
Florisla
¡Gracias, @florisia! Estoy en el proceso de transición de virtualenvwrapper al venv incorporado para la implementación de aplicaciones, y su explicación me dio la plantilla sobre cómo hacerlo. Solo confiaba en la if hasattr(sys, 'real_prefix'):prueba, que ya no funcionaba.
usonianhorizon
8

Puede hacer which pythony ver si apunta al que está en el entorno virtual.

kunrazor
fuente
1
whichno está disponible por defecto en Windows. En su wherelugar, puede usar en Windows o emplear whichcraft . O mira sys.executable. Pero aún así, hay mejores métodos.
florisla
5
  • Actualizado en noviembre de 2019 (adjunto).

Yo uso habitualmente varios entornos virtuales instalados por Anaconda (venv). Este fragmento de código / ejemplos le permite determinar si se encuentra o no en un venv (o en el entorno de su sistema), y también puede requerir un venv específico para su script.

Agregar al script de Python (fragmento de código):

# ----------------------------------------------------------------------------
# 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! ... ]

Ejemplo:

$ 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) $

Actualización 1 - uso en scripts bash:

También puede usar este enfoque en scripts de bash (por ejemplo, aquellos que deben ejecutarse en un entorno virtual específico). Ejemplo (agregado al 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

Actualización 2 [Nov 2019]

Desde mi publicación original, me mudé de Anaconda venv (y Python ha evolucionado en entornos virtuales viz-a-viz ).

Reexaminando este problema, aquí hay un código Python actualizado que puede insertar para probar que está operando en un entorno virtual Python específico (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()

Aquí hay un código explicativo.

[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
fuente
3

La forma más fácil es simplemente ejecutar: which pythonsi está en un virtualenv, apuntará a su pitón en lugar del global.

Silvio Biasiol
fuente
1
No creo que esto realmente responda la pregunta (que está preocupada por el "script actual"). Sin embargo, esto responde a mi pregunta particular, "¿cómo puedo saber si estoy en un entorno virtual desde la línea de comandos"?
ukrutt
1

(editado) Encontré de esa manera, ¿qué piensas de eso? (también devuelve la ruta de base de venv y funciona incluso para readthedocs donde no se verifica la variable env ):

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'] + '/../')

fuente
0

Ya hay muchos métodos excelentes publicados aquí, pero solo agregando uno más:

import site
site.getsitepackages()

te dice dónde están pipinstalados los paquetes.

flujo2k
fuente
Esto no indica si Python se está ejecutando dentro de un entorno virtual o no.
florisla
@florisla ¿Podrías dar más detalles? Si site.getsitepackages()genera un directorio que no es el del sistema, puede deducir que se encuentra en un entorno virtual.
flow2k
Puede instalar Python en múltiples ubicaciones. Por ejemplo, en Windows puede instalar un Python 'sistema' y una distribución WinPython más un Python basado en Conda. Todos estos tienen diferentes carpetas de paquetes de sitio, pero no necesariamente son creados por (o utilizados en) a virtualenv.
florisla
@florisla Buen punto: acabo de ver esto (venv o no) es lo que está preguntando (había escrito una respuesta similar para otra pregunta). Estoy de acuerdo en que esto podría no dar la respuesta segura de si estás en un venv o no, pero podría ayudarte a decirte qué Python o qué venvestás usando.
flow2k
-1

No es a prueba de balas, pero para entornos UNIX prueba simple como

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

funciona muy bien para mi Es más simple que probar los atributos existentes y, de todos modos, debe nombrar su directorio venv venv.

Mate
fuente
-1

En el sistema operativo Windows, ve algo como esto:

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

Los paréntesis significan que en realidad se encuentra en el entorno virtual llamado "virtualEnvName".

se quedan
fuente
Tú y yo podemos leer 'virtualEnvName' muy bien. Pero la pregunta es cómo un módulo Python puede leer esto.
florisla
-1

Una posible solución es:

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

En mi caso, realmente solo quería detectar si podía instalar elementos con pip tal cual. Si bien puede no ser la solución correcta para todos los casos, considere simplemente verificar si tiene permisos de escritura para la ubicación del ejecutable de Python.

Nota: esto funciona en todas las versiones de Python, pero también regresa Truesi ejecuta el sistema Python con sudo. Aquí hay un caso de uso potencial:

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
fuente
-1

Esta es una vieja pregunta, pero muchos ejemplos anteriores son demasiado complicados.

Keep It Simple: (en el terminal Jupyter Notebook o Python 3.7.1 en 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
fuente
Si agrega lógica para verificar la presencia de envsesa ruta, dejará de funcionar cuando se mueva de anaconda a virtualenvo pipenv.
florisla
Florisla, proporcionaste tu respuesta "Cómo no hacerlo" casi 3 meses después de que di una respuesta que me funciona dentro de los límites (no me muevo entre virtualenv y pipenv). Es un mal deporte desestimar las respuestas de otras personas para que se vea mejor.
Rich Lysakowski PhD
Rich, lo que funciona para ti puede no funcionar para otras personas. Puede que ni siquiera funcione para el póster original.
florisla