Determinar se o Python está sendo executado dentro do virtualenv


272

É possível determinar se o script atual está sendo executado dentro de um ambiente virtualenv?


2
Por curiosidade, por que você gostaria de saber disso?
Jorge Leitao

1
ou seja, ser capaz de escrever um script personalizado que gere um prompt para seu shell e você desejar que ele indique se você está em venv ou não, para poder detectar isso de dentro desse código, melhor sem chamar ferramentas externas .
Marcin Orlowski

Respostas:


227

AFAIK, a maneira mais confiável de verificar isso (e a maneira usada internamente no virtualenv e no pip) é verificar a existência de sys.real_prefix:

import sys

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

Dentro de um virtualenv, sys.prefixaponta para o diretório virtualenv, e sys.real_prefixaponta para o prefixo "real" do sistema Python (muitas vezes /usrou /usr/localou algo assim).

Fora de um virtualenv, sys.real_prefixnão deveria existir.

O uso da VIRTUAL_ENVvariável de ambiente não é confiável. Ele é definido pelo activatescript de shell virtualenv , mas um virtualenv pode ser usado sem ativação, executando diretamente um executável do diretório virtualenv bin/(ou Scripts), caso em que $VIRTUAL_ENVnão será definido.


11
Isso não parece mais válido no Python 3.
Dan P.

49
Se você estiver usando virtualenv (github.com/pypa/virtualenv), esta resposta será igualmente correta para Python 2 ou Python 3. Se você estiver usando pyvenv ( legacy.python.org/dev/peps/pep-0405 ), um virtualenv -equivalente incorporado no Python 3.3+ (mas não é o mesmo que virtualenv), ele usa sys.base_prefix em vez de sys.real_prefix, e sys.base_prefix sempre existe; fora de um pyvenv é igual a sys.prefix.
Carl Meyer

2
@ Kounavi Não acho provável que a versão do Windows tenha algum impacto. Esta resposta é parte essencial de como o virtualenv funciona em qualquer plataforma. É possível que você esteja usando Pyven 3 pyvenv, não virtualenv, na máquina Windows 2012? Ou que algo está acontecendo com o PATH e você não está de fato executando no virtualenv quando pensa que está?
Carl Meyer

3
One-liner para scripts bashPYTHON_ENV=$(python -c "import sys; sys.stdout.write('1') if hasattr(sys, 'real_prefix') else sys.stdout.write('0')")
Sam Myers

2
Esta resposta é obsoleta, sem surpresa. Especificamente, esta resposta retorna falsos negativos para casos de uso comuns. Isso é ruim. Em vez disso, consulte: a atualização autorizada da hroncok , detectando corretamente todos os venvs não Anaconda ou a resposta autorizada de Victoria Stuart , detectando corretamente todos os venvs Anaconda . ( Todos os meus upvotes para quem combina essas duas respostas. )
Cecil Curry

97

Tente usar pip -V(aviso capital V)

Se você estiver executando o ambiente virtual. mostrará o caminho para a localização do ambiente.


Se você mudou virtualenvmuito sua situação, é possível que isso possa falhar ou mentir para você. Se está mentindo, você pode fazer find /path/to/venv/ -type f -exec sed -ie "s:/old/path/to/venv:/path/to/venv:g" {} \+. Se estiver falhando (recebi "dados de marechal incorretos"), você precisará limpar os arquivos .pyc com find /path/to/venv -type f -name "*.pyc" -exec rm {} \+(não se preocupe, eles serão reconstruídos automaticamente).
Jeremysprofile 29/10

Acabei de testar isso no Windows 10 com Python 3.7. Ele imprime o local do pip a partir da instalação padrão ...\lib\site-packagesno %PATH%. Portanto, ele retornará um falso positivo nesse caso.
JamesThomasMoon1979 12/02/19

71

Esta é uma melhoria da resposta aceita por Carl Meyer . Ele funciona com virtualenv para Python 3 e 2 e também para o módulo venv no Python 3:

import sys


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

A verificação de sys.real_prefixcovers virtualenv, a igualdade de não-vazio sys.base_prefixcom sys.prefixcovers venv.

Considere um script que usa a função assim:

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

E a seguinte invocação:

$ 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 

4
Uma vez que o Python 3.3 não é mais mantido ou suportado pela maioria dos quadros 3 Python e aplicações, esta função já se reduz a uma única linha de trivial: def is_venv(): return hasattr(sys, 'real_prefix') or sys.base_prefix != sys.prefix. Apenas dizendo'.
23919 Cecil Curry

Infelizmente, isso não parece funcionar com pipenvambientes virtuais criados.
dragon788 24/02

46

Verifique a $VIRTUAL_ENVvariável de ambiente.

A $VIRTUAL_ENVvariável de ambiente contém o diretório do ambiente virtual quando em um ambiente virtual ativo.

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

Depois de executar deactivate/ sair do ambiente virtual, a $VIRTUAL_ENVvariável será limpa / vazia. Python irá gerar um KeyErrorporque a variável de ambiente não está definida.

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

Naturalmente, essas mesmas verificações de variáveis ​​de ambiente também podem ser feitas fora do script Python, no shell.


1
Isso funciona para um virtualenvvirtualenv e um venvvirtualenv.
Florisla 19/09/19

@verboze: como é suposto fazer, certo? Um virtualenv desativado significa que o script do usuário não está sendo executado em um.
MestreLion 8/11

Isso verifica se um virtualenv está ativado, mas isso não significa necessariamente que o processo Python em execução seja desse virtualenv.
erb 19/03

20

De acordo com o virtualenv pep em http://www.python.org/dev/peps/pep-0405/#specification, você pode usar o sys.prefix em vez do os.environ ['VIRTUAL_ENV'].

o sys.real_prefix não existe no meu virtualenv e o mesmo no sys.base_prefix.


8
virtualenv é o projeto independente que funciona em qualquer versão do Python ( github.com/pypa/virtualenv ). O PEP ao qual você se vinculou é para pyvenv, que é baseado em virtualenv, mas é implementado de maneira diferente (melhor) e é incorporado ao Python 3.3+. Esta pergunta é sobre virtualenv, não pyvenv. Você está certo de que em um pyvenv não há sys.real_prefix.
Carl Meyer

5
Uma boa maneira de detectar a partir do bash usando esta resposta é executar: o env |grep VIRTUAL_ENV |wc -l que retornará 1 se estiver em um venv ou 0 se não estiver.
LISTERINE

3
Se você estiver em um shell, você pode simplesmente usar [[ -n $VIRTUAL_ENV ]] && echo virtualenvou [[ -z $VIRTUAL_ENV ]] && echo not virtualenvdependendo de suas necessidades.
6

9

Para verificar se o seu Virtualenv interno:

import os

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

Você também pode obter mais dados sobre o seu ambiente:

import sys
import os

print(f'Python Executable: {sys.executable}')
print(f'Python Version: {sys.version}')
print(f'Virtualenv: {os.getenv("VIRTUAL_ENV")}')

1
Essa é a melhor abordagem de plataforma cruzada (Windows / Unix).
Adi Unnithan

Até agora, essa é apenas a maneira compatível entre plataformas, python 2 e python 3. Obrigado.
RJ

9

Existem várias boas respostas aqui e outras menos robustas. Aqui está uma visão geral.

Como não fazer isso

Não confie na localização do Python ou na site-packagespasta.

Se eles estiverem configurados para locais fora do padrão, isso não significa que você esteja realmente em um ambiente virtual. Os usuários podem ter mais de uma versão do Python instalada, e essas nem sempre são as que você espera.

Evite olhar para:

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

Além disso, não verificar a presença de venv, .venvou envsem qualquer um desses caminhos. Isso ocorrerá em ambientes com um local mais exclusivo. Por exemplo, o Pipenv usa valores de hash como o nome para seus ambientes.

VIRTUAL_ENV variável de ambiente

Ambos virtualenve venvdefina a variável de ambiente $VIRTUAL_ENVao ativar um ambiente. Veja PEP 405 .

Você pode ler essa variável em scripts de shell ou usar esse código Python para determinar se está definido.

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

O problema é que isso só funciona quando o ambiente é ativado pelo activatescript de shell.

Você pode iniciar os scripts do ambiente sem ativar o ambiente ; portanto, se isso for uma preocupação, você precisará usar um método diferente.

sys.base_prefix

virtualenv, venvE pyvenvponto sys.prefixpara o Python instalado dentro do virtualenv como seria de esperar.

Ao mesmo tempo, o valor original de sys.prefixtambém é disponibilizado como sys.base_prefix.

Podemos usar isso para detectar se estamos em um 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

Cair pra trás: sys.real_prefix

Agora, tenha cuidado, virtualenvantes da versão 20 não ter sido definida, sys.base_prefixmas sys.real_prefixsim.

Para estar seguro, marque os dois conforme sugerido na resposta da 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

Se você estiver usando ambientes virtuais do Anaconda, verifique a resposta de Victoria Stuart .


O OP está perguntando "Como eu faço?", Não "Como NÃO?" Essa resposta é um exagero. Isso vai além do espírito da pergunta e ofusca a resposta com muitas variações. Mantenha suas respostas o mais simples possível e responda diretamente à pergunta.
Rich Lysakowski PhD

Estou resumindo as múltiplas respostas aqui e fornecendo conselhos sobre qual delas pode ser correta para circunstâncias específicas. A pergunta original não fornece contexto suficiente para selecionar uma dessas técnicas como a 'melhor' - simplesmente não é assim tão simples.
florisla

1
Na seção para sys.base_prefix, o teste não deve ser:running_in_virtualenv = sys.*base_*prefix != sys.prefix
usonianhorizon 19/06

@usonianhorizon True, obrigado!
florisla 19/06

Obrigado, @florisia! Estou em processo de transição do virtualenvwrapper para o venv interno para implantação de aplicativos, e sua explicação me deu o modelo de como fazê-lo. Eu estava confiando apenas no if hasattr(sys, 'real_prefix'):teste, que não funcionava mais.
usonianhorizon 19/06

8

Você pode fazer which pythone ver se está apontando para o ambiente virtual.


1
whichnão está disponível por padrão no Windows. Em wherevez disso, você pode usar no Windows ou empregar artesanato . Ou olhe sys.executable. Mas, ainda assim, existem métodos melhores.
Florisla 31/10/19

5
  • Atualizado em novembro de 2019 (anexado).

Uso rotineiramente vários ambientes virtuais instalados pelo Anaconda (venv). Este trecho de código / exemplos permite determinar se você está ou não em um venv (ou no ambiente do sistema) e também exige um venv específico para o seu script.

Adicione ao script Python (trecho 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! ... ]

Exemplo:

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

Atualização 1 - use em scripts bash:

Você também pode usar essa abordagem em scripts bash (por exemplo, aqueles que devem ser executados em um ambiente virtual específico). Exemplo (adicionado ao 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

Atualização 2 [novembro de 2019]

Desde o meu post original, mudei de Anaconda venv (e o próprio Python evoluiu ambientes virtuais viz-a-viz ).

Reexaminando esse problema, eis alguns códigos Python atualizados que você pode inserir para testar se está operando em um ambiente 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()

Aqui está um 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!  :-)
>>> 

3

A maneira mais fácil é simplesmente executar which python:, se você estiver em um virtualenv, ele apontará para o python em vez do global


1
Eu não acho que isso realmente responda à pergunta (que está preocupada com o "script atual"). No entanto, isso responde à minha pergunta em particular: "como descobrir se estou em um ambiente virtual a partir da linha de comando".
ukrutt

1

(editada) Encontrei assim, o que você acha disso? (ele também retorna o caminho base venv e funciona mesmo para readthedocs onde a verificação da variável env não):

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

0

Já existem muitos ótimos métodos publicados aqui, mas apenas adicionamos mais um:

import site
site.getsitepackages()

informa onde pipos pacotes foram instalados.


Isso não informa se o Python está sendo executado dentro de um ambiente virtual ou não.
florisla 19/09/19

@florisla Você poderia elaborar? Se site.getsitepackages()gerar um diretório que não seja o sistema, você poderá deduzir que está em um ambiente virtual.
flow2k

Você pode instalar o Python em vários locais. Por exemplo, no Windows, você pode instalar um Python 'system' e uma distribuição WinPython, além de um Python baseado em Conda. Todos eles têm pastas de pacotes de sites diferentes, mas não são necessariamente criados por (ou usados ​​em) a virtualenv.
florisla 20/09/19

Florisla @ Bom ponto - Acabei de ver isso (venv ou não) é o que a pergunta está perguntando (eu tinha escrito uma resposta semelhante para outra pergunta). Concordo que isso pode não dar a resposta certa sobre se você está em um venv ou não, mas pode ajudar a dizer qual Python ou qual venvvocê está usando.
flow2k

-1

Não é à prova de balas, mas para ambientes UNIX, teste simples como

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

funciona muito bem para mim. É mais simples do que testar os atributos existentes e, de qualquer forma, você deve nomear seu diretório venv venv.


-1

No sistema operacional Windows, você vê algo assim:

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

Parênteses significam que você está realmente no ambiente virtual chamado "virtualEnvName".


Você e eu podemos ler 'virtualEnvName' muito bem. Mas a questão é: como um módulo Python pode ler isso.
florisla 19/09/19

-1

Uma solução potencial é:

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

No meu caso, eu realmente só queria detectar se poderia instalar itens com o pip como está. Embora possa não ser a solução certa para todos os casos, considere simplesmente verificar se você possui permissões de gravação para o local do executável do Python.

Nota: isso funciona em todas as versões do Python, mas também retorna Truese você executar o sistema com o Python sudo. Aqui está um 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'])

-1

Esta é uma pergunta antiga, mas muitos exemplos acima são muito complicados.

Mantenha as coisas simples: (no terminal Jupyter Notebook ou Python 3.7.1 no 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'

Se você adicionar lógica para verificar a presença envsdesse caminho, isso parará de funcionar quando você passar do anaconda para virtualenvou pipenv.
florisla 19/09/19

Florisla, você forneceu sua resposta "Como não fazê-lo" quase três meses depois de eu fornecer uma resposta que funciona para mim dentro de limites (eu não me movo entre virtualenv e pipenv). É um esporte ruim rebaixar as respostas de outras pessoas para melhorar sua aparência.
Rich Lysakowski PhD

Rico, o que funciona para você pode não funcionar para outras pessoas. Pode nem funcionar para o pôster original.
florisla
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.