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

272

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

miracle2k
источник
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 
hroncok
источник
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 в оболочке.

MrHetii
источник
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.

chronossc
источник
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, проверьте ответ Виктории Стюарт .

florisla
источник
ОП спрашивает «Как мне?», А не «Как НЕ делать?» Этот ответ является излишним. Это выходит за рамки духа вопроса и запутывает ответ слишком многими вариациями. Пожалуйста, сделайте ваши ответы как можно более простыми и ответьте на вопрос напрямую.
Рич Лысаковски, доктор философии,
Я суммирую здесь несколько ответов и даю советы, какие из них могут быть подходящими для конкретных обстоятельств. Исходный вопрос не дает достаточного контекста для выбора одного из этих методов в качестве «лучшего» - он просто не так прост.
Флорисла
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и посмотреть, если он указывает на тот, в виртуальной среде.

kunrazor
источник
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установлены пакеты.

flow2k
источник
Это не говорит, работает ли 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.

Matt
источник
-1

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

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

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

getleft
источник
Вы и я можем читать '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'
Рич Лысаковский PhD
источник
Если вы добавите логику для проверки наличия envsв этом пути, это перестанет работать при переходе от анаконды к virtualenvили pipenv.
Флорисла
Florisla, вы предоставили свой ответ «Как не делать этого» почти через 3 месяца после того, как я предоставил ответ, который работает для меня в определенных пределах (я не двигаюсь между virtualenv и pipenv). Плохой вид спорта - обесценивать ответы других людей, чтобы улучшить свой внешний вид.
Рич Лысаковски, доктор философии,
Рич, то, что работает для тебя, может не работать для других людей. Это может даже не работать для оригинального плаката.
Флорисла