Визначте, чи працює 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або деякі такі).

Поза virtualenv, sys.real_prefixне повинно існувати.

Використання VIRTUAL_ENVзмінної середовища не є надійним. Він встановлюється activateсценарієм оболонки virtualenv , але virtualenv можна використовувати без активації, безпосередньо запустивши виконуваний файл з каталогу bin/(або Scripts) virtualenv , і в цьому випадку $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 . ( Усі мої нагороди за того, хто поєднує ці дві відповіді. )
Сесіль Керрі

97

Спробуйте скористатися 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. Він друкує місце розташування pip із встановленої за замовчуванням ...\lib\site-packagesу %PATH%. Тож він поверне хибний позитив у такому випадку.
JamesThomasMoon1979,

71

Це вдосконалення прийнятої відповіді Карла Мейєра . Він працює з 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.
florisla

@verboze: як це належить зробити, правда? Відключений virtualenv означає, що сценарій користувача не працює на одному.
MestreLion

Це перевіряє, чи активовано virtualenv, але це не обов'язково означає, що запущений процес Python походить від цього virtualenv.
erb

20

Відповідно до virtualenv pep на 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
Хороший спосіб виявити баш за допомогою цієї відповіді - запустити: env |grep VIRTUAL_ENV |wc -l який поверне значення 1, якщо в venv, або 0, якщо ні.
СПИСОК

3
Якщо ви знаходитесь в оболонці, ви можете просто використовувати [[ -n $VIRTUAL_ENV ]] && echo virtualenvабо [[ -z $VIRTUAL_ENV ]] && echo not virtualenvзалежно від ваших потреб.
Шість

9

Щоб перевірити, чи є ваш всередині 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на встановлений всередині virtualenv Python так, як ви цього очікували.

У той же час початкове значення sys.prefixтакож стає доступним як sys.base_prefix.

Ми можемо використовувати це для виявлення, чи ми знаходимось у віртуальній програмі.

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 Правда, дякую!
florisla

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

8

Ви можете зробити which pythonі подивитися, чи вказує його на віртуальне оточення.


1
whichнедоступно за замовчуванням у Windows. Ви можете whereзамість цього використовувати в Windows, або використовувати який апарат . Або подивіться sys.executable. Але все ж є кращі методи.
флорисла

5
  • Оновлено листопад 2019 року (додається).

Я звичайно використовую кілька встановлених анакондами віртуальних середовищ (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 script):

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 розвивався віз-а-віз візуально візуально віртуальними середовищами).

Переглянувши цю проблему, ось оновлений код 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, він вкаже на його python замість глобального


1
Я не думаю, що це насправді відповідає на питання (яке стосується "поточного сценарію"). Однак це відповідає на моє конкретне запитання, "як я дізнаюся, чи перебуваю у віртуальному середовищі з командного рядка".
ukrutt

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

@florisla Ви могли б детальніше розробитись? Якщо site.getsitepackages()виводить каталог, який не є системним, ви можете встановити, що ви знаходитесь у віртуальному середовищі.
flow2k

Ви можете встановити Python у кількох місцях. Наприклад, у Windows можна встановити "системний" Python та дистрибутив WinPython плюс Python на основі Conda. Усі вони мають різні папки веб-сайтів, але не обов'язково створюються (або використовуються) a virtualenv.
florisla

@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 може це прочитати.
florisla

-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 Notebook або 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). Погано займатися спортом, щоб заохочувати відповіді інших людей, щоб зробити ваш власний вигляд кращим.
Багатий доктор фізичних наук

Багаті, те, що працює для вас, може не працювати для інших людей. Це може не працювати навіть для оригінального плаката.
florisla
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.