Sprawdź, czy Python działa wewnątrz virtualenv

272

Czy można ustalić, czy bieżący skrypt działa w środowisku virtualenv?

miracle2k
źródło
2
Z ciekawości, dlaczego chcesz to wiedzieć?
Jorge Leitao,
1
tzn. być w stanie napisać niestandardowy skrypt, który generuje monit dla powłoki i chcesz, aby ten monit wskazywał, czy jesteś w venv, czy nie, więc chcesz być w stanie wykryć to z poziomu tego kodu, najlepiej bez wywoływania zewnętrznych narzędzi .
Marcin Orłowski,

Odpowiedzi:

227

AFAIK najbardziej niezawodnym sposobem sprawdzenia tego (i sposobem, który jest używany wewnętrznie w virtualenv i pip) jest sprawdzenie, czy istnieją sys.real_prefix:

import sys

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

Wewnątrz virtualenv, sys.prefixwskazuje katalog virtualenv i sys.real_prefixwskazuje na „prawdziwe” prefiks systemu Pythona (często /usrlub /usr/localczy coś takiego).

Poza virtualenv sys.real_prefixnie powinno istnieć.

Korzystanie ze VIRTUAL_ENVzmiennej środowiskowej nie jest niezawodne. Jest ustawiony przez activateskrypt powłoki virtualenv , ale virtualenv może być używany bez aktywacji poprzez bezpośrednie uruchomienie pliku wykonywalnego z katalogu bin/(lub Scripts) virtualenv , w którym to przypadku $VIRTUAL_ENVnie zostanie ustawiony.

Carl Meyer
źródło
11
Nie wydaje się to już poprawne w Pythonie 3.
Dan P.
49
Jeśli używasz virtualenv (github.com/pypa/virtualenv), ta odpowiedź jest równie poprawna dla Python 2 lub Python 3. Jeśli używasz pyvenv ( legacy.python.org/dev/peps/pep-0405 ), virtualenv -equivalent wbudowany w Python 3.3+ (ale nie to samo co virtualenv), następnie używa sys.base_prefix zamiast sys.real_prefix, a sys.base_prefix zawsze istnieje; poza pyvenv jest równy sys.prefiks.
Carl Meyer
2
@Kounavi Nie sądzę, aby wersja Windows miała jakikolwiek wpływ. Ta odpowiedź jest podstawową częścią działania virtualenv na dowolnej platformie. Czy to możliwe, że używasz Python 3 pyvenv, a nie virtualenv, na komputerze z systemem Windows 2012? A może coś dzieje się ze ŚCIEŻKĄ, a tak naprawdę nie działa się w virtualenv, kiedy tak myślisz?
Carl Meyer,
3
One-liner do skryptów bashPYTHON_ENV=$(python -c "import sys; sys.stdout.write('1') if hasattr(sys, 'real_prefix') else sys.stdout.write('0')")
Sam Myers
2
Ta odpowiedź jest, jak można się spodziewać , przestarzała . W szczególności ta odpowiedź zwraca fałszywe negatywy dla typowych przypadków użycia. To źle. Zamiast widzieć albo: hroncok jest autorytatywny aktualizacja prawidłowo wykrywa wszystkie Pomieszczenia Anaconda venvs lub Victoria Stuart 's autorytatywny odpowiedź prawidłowo wykrywa wszystkie Anaconda venvs . ( Wszystkie moje głosy poparcia dla tego, kto łączy te dwie odpowiedzi ) .
Cecil Curry
97

Spróbuj użyć pip -V(wypowiedz kapitał V)

Jeśli korzystasz z wirtualnej env. pokaże ścieżkę do lokalizacji środowiska.

loki l
źródło
Jeśli virtualenvczęsto się poruszałeś , możliwe, że to się nie powiedzie lub okłamie. Jeśli kłamie, możesz to zrobić find /path/to/venv/ -type f -exec sed -ie "s:/old/path/to/venv:/path/to/venv:g" {} \+. Jeśli zawiedzie (mam „złe dane marszałka”), musisz wyczyścić pliki .pyc find /path/to/venv -type f -name "*.pyc" -exec rm {} \+(nie martw się, odbudują się automatycznie).
jeremysprofile
Właśnie przetestowałem to na Windows 10 z Python 3.7. Wyświetla lokalizację pip z domyślnej instalacji ...\lib\site-packagesw %PATH%. W takim przypadku zwróci fałszywie dodatni wynik.
JamesThomasMoon1979
71

Jest to poprawka do zaakceptowanej odpowiedzi Carla Meyera . Działa z virtualenv dla Python 3 i 2, a także z modułem venv w Python 3:

import sys


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

Sprawdzanie sys.real_prefixokładek virtualenv, równość niepustych sys.base_prefixz sys.prefixcoverami venv.

Rozważmy skrypt, który używa takiej funkcji:

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

I następujące wywołanie:

$ 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
źródło
4
Od Pythona 3.3 nie jest już utrzymywana i obsługiwany przez większość Pythonie 3 ramy i aplikacji, funkcja ogranicza się do banalnej jedną wkładką: def is_venv(): return hasattr(sys, 'real_prefix') or sys.base_prefix != sys.prefix. Tylko mówię'.
Cecil Curry
Niestety nie wydaje się, aby działało to w pipenvutworzonych środowiskach wirtualnych.
dragon788
46

Sprawdź $VIRTUAL_ENVzmienną środowiskową.

$VIRTUAL_ENVZmienna zawiera katalog środowisku wirtualnym, gdy w aktywnym środowisku wirtualnym.

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

Po uruchomieniu deactivate/ opuszczeniu środowiska wirtualnego $VIRTUAL_ENVzmienna zostanie wyczyszczona / pusta. Python podniesie, KeyErrorponieważ zmienna środowiskowa została rozbrojona.

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

Te same kontrole zmiennych środowiskowych można oczywiście również wykonać poza skryptem Pythona w powłoce.

MrHetii
źródło
1
Działa to zarówno dla virtualenvvirtualenv, jak i venvvirtualenv.
florisla,
@verboze: tak jak powinno, prawda? Dezaktywowany virtualenv oznacza, że ​​skrypt użytkownika nie działa na jednym.
MestreLion,
To sprawdza, czy virtualenv jest aktywowany, ale to niekoniecznie oznacza, że ​​uruchomiony jest proces Pythona z tego virtualenv.
erb
20

Według virtualenv pep na http://www.python.org/dev/peps/pep-0405/#specification możesz po prostu użyć sys.prefix zamiast os.environ ['VIRTUAL_ENV'].

sys.real_prefix nie istnieje w mojej virtualenv i to samo z sys.base_prefix.

chronossc
źródło
8
virtualenv to samodzielny projekt, który działa na dowolnej wersji Pythona ( github.com/pypa/virtualenv ). PEP, z którym się łączysz, jest przeznaczony dla pyvenv, który jest oparty na virtualenv, ale jest zaimplementowany inaczej (lepiej) i jest wbudowany w Python 3.3+. To pytanie dotyczy virtualenv, a nie pyvenv. Masz rację, że w pyvenv nie ma sys.real_prefix.
Carl Meyer
5
Dobrym sposobem na wykrycie po bashu za pomocą tej odpowiedzi jest uruchomienie: env |grep VIRTUAL_ENV |wc -l która zwróci 1 jeśli w venv lub 0 jeśli nie.
LISTERINE
3
Jeśli jesteś w powłoce, możesz po prostu użyć [[ -n $VIRTUAL_ENV ]] && echo virtualenvlub w [[ -z $VIRTUAL_ENV ]] && echo not virtualenvzależności od potrzeb.
Sześć
9

Aby sprawdzić, czy Twój wirtualny Virtualenv:

import os

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

Możesz także uzyskać więcej danych o swoim środowisku:

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
źródło
1
Jest to najlepsze podejście wieloplatformowe (Windows / Unix).
Adi Unnithan
Jak dotąd jest to tylko sposób zgodny z wieloma platformami, python 2 i python 3. Dzięki.
RJ
9

Jest tu wiele dobrych odpowiedzi i niektóre mniej niezawodne. Oto przegląd.

Jak tego nie robić?

Nie polegaj na lokalizacji Pythona ani site-packagesfolderu.

Jeśli są ustawione na niestandardowe lokalizacje, nie oznacza to, że faktycznie znajdujesz się w środowisku wirtualnym. Użytkownicy mogą mieć zainstalowaną więcej niż jedną wersję Pythona i nie zawsze są tam, gdzie się ich spodziewasz.

Unikaj patrzenia na:

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

Nie należy również sprawdzić pod kątem obecności venv, .venvani envsw żadnym z tych ścieżek. To zepsuje się w środowiskach o bardziej unikalnej lokalizacji. Na przykład Pipenv używa wartości skrótu jako nazwy swoich środowisk.

VIRTUAL_ENV Zmienna środowiskowa

Zarówno virtualenvi venvustaw zmienną środowiskową $VIRTUAL_ENVpodczas aktywacji środowiska. Zobacz PEP 405 .

Możesz odczytać tę zmienną w skryptach powłoki lub użyć tego kodu Python, aby ustalić, czy jest ustawiona.

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

Problem polega na tym, że działa to tylko wtedy, gdy środowisko jest aktywowane przez activateskrypt powłoki.

Możesz uruchamiać skrypty środowiska bez aktywowania środowiska , więc jeśli jest to problem, musisz użyć innej metody.

sys.base_prefix

virtualenv, venvi pyvenvwskaż sys.prefixPython zainstalowany wewnątrz virtualenv, jak można się spodziewać.

Jednocześnie udostępniana jest również pierwotna wartość parametru .sys.prefixsys.base_prefix

Możemy to wykorzystać do wykrycia, czy jesteśmy wirtualni.

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

Fallback: sys.real_prefix

Teraz uważaj, virtualenvzanim wersja 20 nie ustawiła się, sys.base_prefixale ustawiła się sys.real_prefix.

Aby być bezpiecznym, sprawdź oba, jak sugeruje odpowiedź 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

Anakonda

Jeśli używasz środowisk wirtualnych Anaconda, sprawdź odpowiedź Victorii Stuart .

florisla
źródło
OP pyta „Jak mam?”, A nie „Jak NIE?” Ta odpowiedź to przesada. Wykracza poza ducha pytania i zaciemnia odpowiedź zbyt wieloma odmianami. Prosimy o możliwie najprostsze odpowiedzi i bezpośrednie udzielenie odpowiedzi na pytanie.
Rich Lysakowski PhD
Podsumowuję tutaj wiele odpowiedzi i udzielam porad, które z nich mogą być odpowiednie w określonych okolicznościach. Pierwotne pytanie nie zapewnia wystarczającego kontekstu, aby wybrać jedną z tych technik jako „najlepszą” - po prostu nie jest to takie proste.
florisla
1
W sekcji dotyczącej sys.base_prefix nie powinien być test:running_in_virtualenv = sys.*base_*prefix != sys.prefix
usonianhorizon
@usonianhorizon Prawda, dziękuję!
florisla
Dziękuję, @florisia! Jestem w trakcie przejścia z virtualenvwrapper do wbudowanego venv do wdrażania aplikacji, a twoje wyjaśnienie dało mi szablon, jak to zrobić. Polegałem tylko na if hasattr(sys, 'real_prefix'):teście, który już nie działał.
usonianhorizon
8

Możesz to zrobić which pythoni sprawdzić, czy wskazuje na to w wirtualnej env.

Kunrazor
źródło
1
whichnie jest domyślnie dostępny w systemie Windows. Możesz wherezamiast tego użyć w systemie Windows lub zatrudnić które jednostki . Lub spójrz na sys.executable. Ale wciąż istnieją lepsze metody.
florisla
5
  • Zaktualizowany listopad 2019 (dołączony).

Rutynowo korzystam z kilku środowisk wirtualnych zainstalowanych przez Anacondę (venv). Ten fragment kodu / przykłady pozwala określić, czy jesteś w venv (lub środowisku systemowym), a także wymagać określonej venv dla skryptu.

Dodaj do skryptu Python (fragment kodu):

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

Przykład:

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

Aktualizacja 1 - użyj w skryptach bash:

Możesz także użyć tego podejścia w skryptach bash (np. Tych, które muszą działać w określonym środowisku wirtualnym). Przykład (dodany do skryptu 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

Aktualizacja 2 [lis 2019]

Od czasu mojego oryginalnego postu przeszedłem z Anaconda venv (a sam Python ewoluował w środowiskach wirtualnych viz-a-viz ).

Ponownie sprawdzając ten problem, oto zaktualizowany kod Pythona, który można wstawić w celu przetestowania działania w określonym środowisku wirtualnym Python (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()

Oto kod wyjaśniający.

[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
źródło
3

Najprościej jest po prostu uruchomić: which pythonjeśli jesteś w virtualenv, wskaże on pytona zamiast globalnego

Silvio Biasiol
źródło
1
Nie sądzę, że to faktycznie odpowiada na pytanie (które dotyczy „obecnego skryptu”). Odpowiada to jednak na moje szczególne pytanie: „jak mogę sprawdzić, czy jestem w środowisku wirtualnym z poziomu wiersza poleceń”.
ukrutt
1

(edytowane) Znalazłem w ten sposób, co o tym sądzisz? (zwraca również ścieżkę bazową venv i działa nawet dla readthedocs, w których nie sprawdza się zmiennej 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'] + '/../')

źródło
0

Istnieje już wiele świetnych metod, ale wystarczy dodać jeszcze jedną:

import site
site.getsitepackages()

informuje, gdzie pipzainstalowano pakiety.

flow2k
źródło
Nie mówi to, czy Python działa w środowisku wirtualnym, czy nie.
florisla,
@florisla Czy mógłbyś opracować? Jeśli site.getsitepackages()wyprowadza katalog, który nie jest systemowy, możesz wywnioskować, że jesteś w środowisku wirtualnym.
flow2k,
Możesz zainstalować Python w wielu lokalizacjach. Na przykład w systemie Windows można zainstalować „systemowy” Python i dystrybucję WinPython oraz Python oparty na Condie. Wszystkie mają różne foldery pakietów witryn, ale niekoniecznie są tworzone przez (lub używane w) a virtualenv.
florisla,
@florisla Dobra uwaga - właśnie widziałem to (Venv czy nie), o to pyta pytanie (napisałem podobną odpowiedź na inne pytanie). Zgadzam się, że może to nie dać jednoznacznej odpowiedzi na pytanie, czy jesteś w venvie, czy nie, ale może pomóc ci powiedzieć, którego Pythona lub którego venvużywasz.
flow2k
-1

To nie jest kuloodporny, ale dla środowisk UNIX prosty test jak

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

działa dla mnie świetnie. To prostsze niż testowanie istnienia jakiegoś atrybutu, w każdym razie powinieneś nazwać swój katalog venv venv.

Matt
źródło
-1

W systemie operacyjnym Windows widać coś takiego:

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

Nawiasy oznaczają, że faktycznie znajdujesz się w środowisku wirtualnym o nazwie „virtualEnvName”.

getleft
źródło
Ty i ja możemy dobrze przeczytać „virtualEnvName”. Ale pytanie brzmi, w jaki sposób moduł Python może to odczytać.
florisla,
-1

Potencjalnym rozwiązaniem jest:

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

W moim przypadku naprawdę chciałem po prostu sprawdzić, czy mogę zainstalować elementy za pomocą pipa w takiej postaci, w jakiej są. Chociaż może to nie być właściwe rozwiązanie dla wszystkich przypadków, rozważ po prostu sprawdzenie, czy masz uprawnienia do zapisu dla lokalizacji pliku wykonywalnego Python.

Uwaga: działa to we wszystkich wersjach Pythona, ale zwraca również, Truejeśli uruchomisz systemowy Python sudo. Oto potencjalny przypadek użycia:

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
źródło
-1

To stare pytanie, ale zbyt wiele powyższych przykładów jest zbyt skomplikowanych.

Keep It Simple: (w Jupyter Notebook lub Python 3.7.1 terminal w systemie 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'
Dr Rich Lysakowski
źródło
Jeśli dodasz logikę do sprawdzania obecności envsna tej ścieżce, przestanie ona działać po przejściu z anakondy do virtualenvlub pipenv.
florisla,
Florisla, udzieliłeś odpowiedzi „Jak tego nie robić” prawie 3 miesiące po tym, jak udzieliłem odpowiedzi, która działa dla mnie w określonych granicach (nie poruszam się między virtualenv i pipenv). Słabym sportem jest zaniżanie odpowiedzi innych ludzi, aby poprawić swój wygląd.
Rich Lysakowski PhD
Bogaty, to, co działa dla Ciebie, może nie działać dla innych ludzi. Może nie działać nawet w przypadku oryginalnego plakatu.
florisla