Определите, работает ли Python внутри virtualenv


272

Можно ли определить, работает ли текущий скрипт в среде virtualenv?


2
Из любопытства, зачем тебе это знать?
— Хорхе Лейтао

1
то есть, чтобы иметь возможность написать собственный скрипт, который генерирует приглашение для вашей оболочки, и вы хотите, чтобы это приглашение указывало, находитесь ли вы в venv или нет, поэтому вы хотите иметь возможность обнаруживать это из этого кода, лучше всего без вызова внешних инструментов ,
— Марцин Орловский

Ответы:


227

AFAIK самый надежный способ проверить это (и способ, который используется внутренне в virtualenv и в pip) - это проверить наличие sys.real_prefix:

import sys

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

Внутри virtualenv, sys.prefixуказывает на каталог virtualenv, и sys.real_prefixуказывает на «реальной» префиксом системы Python (часто /usrили /usr/localили некоторые такие).

Вне виртуальности sys.real_prefixне должно существовать.

Использование VIRTUAL_ENVпеременной окружения ненадежно. Он устанавливается activateсценарием оболочки virtualenv , но virtualenv можно использовать без активации, напрямую запустив исполняемый файл из каталога virtualenv bin/(или Scripts), в этом случае $VIRTUAL_ENVон не будет установлен.


11
Кажется, это больше не действует в Python 3.
— Дэн П.

49
Если вы используете virtualenv (github.com/pypa/virtualenv), этот ответ одинаково корректен для Python 2 или Python 3. Если вы используете pyvenv ( legacy.python.org/dev/peps/pep-0405 ), virtualenv -эквивалент, встроенный в Python 3.3+ (но не то же самое, что virtualenv), затем он использует sys.base_prefix вместо sys.real_prefix, а sys.base_prefix всегда существует; за пределами pyvenv он равен sys.prefix.
— Карл Мейер

2
@ Kounavi Не думаю, что версия для Windows окажет какое-либо влияние. Этот ответ является основной частью того, как virtualenv работает на любой платформе. Возможно ли, что вы используете Python 3 pyvenv, а не virtualenv, на компьютере с Windows 2012? Или что-то происходит с PATH, и вы на самом деле не работаете в virtualenv, когда вы так думаете?
— Карл Мейер

3
Одна PYTHON_ENV=$(python -c "import sys; sys.stdout.write('1') if hasattr(sys, 'real_prefix') else sys.stdout.write('0')")
— Сэм Майерс

2
Этот ответ устарел, что неудивительно. В частности, этот ответ возвращает ложные отрицания для общих случаев использования. Это плохо. Вместо этого см либо: hroncok «s авторитетное обновления правильно обнаруживать все не-Anaconda venvs или Виктория Стюарт » s авторитетный ответ правильно обнаруживать весь Anaconda venvs . ( Все мои благодарности за тех, кто объединяет эти два ответа. )
— Сесил Карри

98

Попробуйте использовать pip -V(обратите внимание, заглавная V)

Если вы работаете в виртуальной среде. это покажет путь к местоположению env.


Если вы много перемещали virtualenv, возможно, это может не сработать или обманывать вас. Если он врет, вы можете сделать find /path/to/venv/ -type f -exec sed -ie "s:/old/path/to/venv:/path/to/venv:g" {} \+. Если это не удастся (я получил «неверные данные маршала»), вам нужно будет стереть файлы .pyc find /path/to/venv -type f -name "*.pyc" -exec rm {} \+(не волнуйтесь, они восстановятся автоматически).
— jeremysprofile

Я только что проверил это на Windows 10 с Python 3.7. Он печатает расположение пункта из установки по умолчанию ...\lib\site-packagesв %PATH%. Таким образом, он вернет ложное срабатывание в этом случае.
— JamesThomasMoon1979

72

Это улучшение принятого ответа Карла Мейера . Он работает с virtualenv для Python 3 и 2, а также для модуля venv в Python 3:

import sys


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

Проверка на sys.real_prefixобложки virtualenv, равенство непустых sys.base_prefixс sys.prefixобложками venv.

Рассмотрим скрипт, который использует такую ​​функцию:

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

И следующий вызов:

$ 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
Поскольку Python 3.3 больше не поддерживаются или поддерживаются большинство Python 3 рамок и приложений, эта функция сводится теперь к тривиальному однострочнику: def is_venv(): return hasattr(sys, 'real_prefix') or sys.base_prefix != sys.prefix. Просто говорю'.
— Сесил Карри

К сожалению, это не похоже на работу с pipenvсозданными виртуальными средами.
— dragon788

46

Проверьте $VIRTUAL_ENVпеременную среды.

$VIRTUAL_ENVПеременная среды содержит каталог виртуальной среды, когда в активной виртуальной среде.

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

После запуска deactivate/ выхода из виртуальной среды $VIRTUAL_ENVпеременная будет очищена / пуста. Python вызовет a, KeyErrorпотому что переменная окружения была не установлена.

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

Те же самые проверки переменных среды, конечно же, можно выполнять и вне скрипта Python в оболочке.


1
Это работает как для virtualenvvirtualenv, так и для venvvirtualenv.
— Флорисла

@verboze: как это должно быть, верно? Деактивированный virtualenv означает, что пользовательский скрипт не запущен на одном из них.
— MestreLion

Это проверяет, активирован ли virtualenv, но это не обязательно означает, что процесс Python выполняется из этого virtualenv.
— Еврорадио

20

Согласно сообщению virtualenv на http://www.python.org/dev/peps/pep-0405/#specification вы можете просто использовать sys.prefix вместо os.environ ['VIRTUAL_ENV'].

sys.real_prefix не существует в моем virtualenv и не отличается от sys.base_prefix.


8
virtualenv - это отдельный проект, который работает на любой версии Python ( github.com/pypa/virtualenv ). PEP, с которым вы связаны, предназначен для pyvenv, который основан на virtualenv, но реализован по-другому (лучше) и встроен в Python 3.3+. Этот вопрос о virtualenv, а не о pyvenv. Ты прав, что в пывенве нет sys.real_prefix.
— Карл Мейер

5
Хороший способ обнаружить bash с помощью этого ответа - запустить: env |grep VIRTUAL_ENV |wc -l который вернет 1, если в venv, или 0, если нет.
— LISTERINE

3
Если вы находитесь в оболочке, вы можете просто использовать [[ -n $VIRTUAL_ENV ]] && echo virtualenvили в [[ -z $VIRTUAL_ENV ]] && echo not virtualenvзависимости от ваших потребностей.
— шесть

10

Чтобы проверить, есть ли у вас внутри Virtualenv:

import os

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

Вы также можете получить больше данных о вашей среде:

import sys
import os

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

1
Это лучший кроссплатформенный (Windows / Unix) подход.
— Ади Уннитан

Пока что это только кроссплатформенный, Python 2 и Python 3 совместимый способ. Спасибо.
— RJ

9

Здесь есть несколько хороших ответов, и некоторые менее надежные. Вот обзор.

Как не сделать это

Не полагайтесь на расположение Python или site-packagesпапку.

Если они установлены в нестандартных местах, это не значит, что вы находитесь в виртуальной среде. Пользователи могут иметь более одной установленной версии Python, и это не всегда так, как вы ожидаете.

Избегайте смотреть на:

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

Кроме того , не проверяют на наличие venv, .venvили envsв любом из этих путей. Это сломается для сред с более уникальным местоположением. Например, Pipenv использует хеш-значения в качестве имени для своей среды.

VIRTUAL_ENV переменная окружения

Оба virtualenvи venvустановите переменную окружения $VIRTUAL_ENVпри активации окружения. Смотри PEP 405 .

Вы можете прочитать эту переменную в сценариях оболочки или использовать этот код Python, чтобы определить, установлена ​​ли она.

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

Проблема заключается в том , что это работает только тогда , когда среда активируется с помощью activateсценария оболочки.

Вы можете запустить сценарии среды не активируя ее , поэтому, если вас это беспокоит, вы должны использовать другой метод.

sys.base_prefix

virtualenv, venv И pyvenvточка sys.prefixв Python установлен внутри virtualenv , как можно было бы ожидать.

В то же время первоначальная стоимость sys.prefixтакже доступна как sys.base_prefix.

Мы можем использовать это, чтобы определить, находимся ли мы в 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

Отступать: sys.real_prefix

Теперь следите, virtualenvдо 20 версии не устанавливалиsys.base_prefix а установилась sys.real_prefixвместо этого.

Так что, чтобы быть в безопасности, проверьте оба, как предложено в ответе 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, проверьте ответ Виктории Стюарт .


ОП спрашивает «Как мне?», А не «Как НЕ делать?» Этот ответ является излишним. Это выходит за рамки духа вопроса и запутывает ответ слишком многими вариациями. Пожалуйста, сделайте ваши ответы как можно более простыми и ответьте на вопрос напрямую.
— Рич Лысаковски, доктор философии,

Я суммирую здесь несколько ответов и даю советы, какие из них могут быть подходящими для конкретных обстоятельств. Исходный вопрос не дает достаточного контекста для выбора одного из этих методов в качестве «лучшего» - он просто не так прост.
— Флорисла

1
В разделе для sys.base_prefix тест не должен быть:running_in_virtualenv = sys.*base_*prefix != sys.prefix
— usonianhorizon

@usonianhorizon Правда, спасибо!
— Флорисла

Спасибо, @florisia! Я нахожусь в процессе перехода от virtualenvwrapper к встроенному venv для развертывания приложений, и ваше объяснение дало мне шаблон того, как это сделать. Я полагался только на if hasattr(sys, 'real_prefix'):тест, который больше не работал.
— usonianhorizon

8

Вы можете сделать which pythonи посмотреть, если он указывает на тот, в виртуальной среде.


1
whichпо умолчанию недоступно в Windows. Вы можете использовать whereвместо этого в Windows, или использовать whichcraft . Или посмотрите на sys.executable. Но все же есть лучшие методы.
— Флорисла

5
  • Обновлено ноябрь 2019 г. (добавлено).

Я обычно использую несколько установленных Anaconda виртуальных сред (venv). Этот фрагмент кода / примеры позволяет вам определить, находитесь ли вы в venv (или в вашей системной среде), а также для запроса конкретного сценария venv.

Добавить в скрипт Python (фрагмент кода):

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

Пример:

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

Обновление 1 - используйте в скриптах bash:

Вы также можете использовать этот подход в скриптах bash (например, тех, которые должны работать в определенной виртуальной среде). Пример (добавлен в скрипт 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

Обновление 2 [ноябрь 2019]

Со времени моего первоначального поста я перешел от Anaconda venv (и сам Python эволюционировал viz-a-viz виртуальные среды ).

Пересматривая эту проблему, вот обновленный код Python, который вы можете вставить, чтобы проверить, что вы работаете в определенной виртуальной среде 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()

Вот некоторый пояснительный код.

[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

Самый простой способ - просто запустить: which pythonесли вы в virtualenv, он будет указывать на свой питон вместо глобального


1
Я не думаю, что это действительно отвечает на вопрос (который касается "текущего сценария"). Однако это отвечает на мой конкретный вопрос: «Как мне узнать, нахожусь ли я в виртуальной среде из командной строки».
— Укрутт

1

(отредактировано) Я нашел этот путь, что вы думаете об этом? (он также возвращает базовый путь venv и работает даже для readthedocs, где проверка переменной 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'] + '/../')

0

Здесь уже опубликовано много отличных методов, но добавим еще один:

import site
site.getsitepackages()

говорит вам, где pipустановлены пакеты.


Это не говорит, работает ли Python в виртуальной среде или нет.
— Флорисла

@florisla Не могли бы вы уточнить? Если site.getsitepackages()выводит каталог, который не является системным, вы можете сделать вывод, что находитесь в виртуальной среде.
— flow2k

Вы можете установить Python в нескольких местах. Например, в Windows вы можете установить «системный» Python и дистрибутив WinPython, а также Python на основе Conda. Все они имеют разные папки с пакетами сайта, но не обязательно создаются (или используются) a virtualenv.
— Флорисла

@florisla Хороший вопрос - я только что понял (Венв или нет), что вопрос задает (я написал аналогичный ответ для другого вопроса). Я согласен, что это может не дать верного ответа относительно того, находитесь ли вы в venv или нет, но может помочь вам сказать, какой Python или какой venvвы используете.
— flow2k

-1

Это не пуленепробиваемый, но для сред UNIX простой тест, такой как

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

отлично работает для меня Это проще, чем тестировать существующий некоторый атрибут, и, в любом случае, вы должны назвать свой каталог venv venv.


-1

В ОС Windows вы видите что-то вроде этого:

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

Скобки означают, что вы на самом деле находитесь в виртуальной среде, называемой «virtualEnvName».


Вы и я можем читать 'virtualEnvName' просто отлично. Но вопрос в том, как модуль Python может это прочитать.
— Флорисла

-1

Потенциал решение:

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

В моем случае я просто хотел определить, могу ли я устанавливать элементы с помощью pip как есть. Хотя это может быть не правильным решением для всех случаев, попробуйте просто проверить, есть ли у вас разрешения на запись для расположения исполняемого файла Python.

Примечание: это работает во всех версиях Python, но также возвращается, Trueесли вы запускаете систему с Python sudo. Вот потенциальный вариант использования:

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

Это старый вопрос, но приведенные выше примеры слишком сложны.

Сохраняйте это простым: (в ноутбуке Jupyter или терминале Python 3.7.1 в 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'

Если вы добавите логику для проверки наличия envsв этом пути, это перестанет работать при переходе от анаконды к virtualenvили pipenv.
— Флорисла

Florisla, вы предоставили свой ответ «Как не делать этого» почти через 3 месяца после того, как я предоставил ответ, который работает для меня в определенных пределах (я не двигаюсь между virtualenv и pipenv). Плохой вид спорта - обесценивать ответы других людей, чтобы улучшить свой внешний вид.
— Рич Лысаковски, доктор философии,

Рич, то, что работает для тебя, может не работать для других людей. Это может даже не работать для оригинального плаката.
— Флорисла
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.