Pythonがvirtualenv内で実行されているかどうかを確認する


272

現在のスクリプトがvirtualenv環境内で実行されているかどうかを確認することはできますか?


2
好奇心から、なぜそれを知りたいのですか?
ホルヘレイタオ2018

1
つまり、シェルのプロンプトを生成するカスタムスクリプトを記述できるようにし、そのプロンプトでvenvにいるかどうかを示したいので、そのコード内から外部ツールを呼び出さずにそれを検出できるようにしたい。
Marcin Orlowski

回答:


227

これを確認する最も信頼できる方法(および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環境変数の使用は信頼できません。これはvirtualenv activateシェルスクリプトによって設定されますが、virtualenvのbin/(またはScripts)ディレクトリから実行可能ファイルを直接実行することにより、アクティベーションなしでvirtualenvを使用できます$VIRTUAL_ENV


11
これはPython 3ではもう有効ではないようです。
Dan P.

49
virtualenv(github.com/pypa/virtualenv)を使用している場合、この回答はPython 2またはPython 3でも同じです。pyvenv(legacy.python.org/dev/peps/pep-0405)を使用している場合、virtualenv -Python 3.3以降に組み込まれている同等のもの(ただし、virtualenvとは異なります)では、sys.real_prefixの代わりにsys.base_prefixを使用し、sys.base_prefixは常に存在します。pyvenv外では、sys.prefixと同じです。
カールマイヤー

2
@Kounavi Windowsのバージョンが影響を与える可能性は低いと思います。この回答は、virtualenvがどのプラットフォームで機能するかの中核となる部分です。Windows 2012マシンでvirtualenvではなくPython 3 pyvenvを使用している可能性はありますか?または、PATHで何かが起こっていて、実際にはvirtualenvで実行していないと思いますか?
Carl Meyer、

3
bashスクリプトのワンライナーPYTHON_ENV=$(python -c "import sys; sys.stdout.write('1') if hasattr(sys, 'real_prefix') else sys.stdout.write('0')")
Sam Myers

2
この答えは当然、時代遅れです。具体的には、この回答は一般的なユースケースの偽陰性を返します。それは良くないね。代わりに、hroncok信頼できる更新がすべての非Anaconda venvを正しく検出するか、またはVictoria Stuart信頼できる回答がすべてのAnaconda venvを正しく検出するかのいずれかを参照してください。(すべてのこれら2つの答えを兼ね備えた誰のための私のupvotes。
セシルカレー

97

pip -V(通知大文字V)を使用してみてください

仮想環境を実行している場合。環境の場所へのパスが表示されます。


あなたが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

私はこれをPython 3.7がインストールされたWindows 10でテストしました。これは、デフォルトからピップの場所は、インストール印刷さ...\lib\site-packages%PATH%。したがって、その場合は誤検知が返されます。
JamesThomasMoon1979

71

これは、カールマイヤーが認めた回答の改善版です。Python 3および2のvirtualenvで動作し、Python 3のvenvモジュールでも動作します。

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_prefixsys.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フレームワークおよびアプリケーションで保守またはサポートされなくなったため、この関数は単純な1行になりました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変数はクリア/空になります。KeyError環境変数が設定されていないため、Pythonはを発生させます。

>>> 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とvirtualenvの両方でvenv機能します。
florisla

@verboze:当然のことながら、そうですか?非アクティブ化されたvirtualenvは、ユーザースクリプトが実行されていないことを意味します。
MestreLion

これはvirtualenvがアクティブ化されているかどうかをチェックしますが、実行中のPythonプロセスがそのvirtualenvからのものであるとは限りません。
ERB

20

http://www.python.org/dev/peps/pep-0405/#specificationのvirtualenv pepによると、os.environ ['VIRTUAL_ENV']の代わりにsys.prefixを使用できます。

sys.real_prefixは私のvirtualenvには存在せず、sys.base_prefixと同じです。


8
virtualenvは、任意のPythonバージョンで動作するスタンドアロンプ​​ロジェクトです(github.com/pypa/virtualenv)。リンクしたPEPはpyvenv用で、virtualenvに基づいていますが、実装方法が異なり(より優れています)、Python 3.3以降に組み込まれています。この質問はpyvenvではなくvirtualenvに関するものです。pyvenvにはがないことは正しいですsys.real_prefix
カールマイヤー

5
この回答を使用してbashから検出する良い方法は、実行することです。 env |grep VIRTUAL_ENV |wc -l これは、envの場合は1を返し、そうでない場合は0を返します。
リステリン2014年

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)アプローチです。
Adi Unnithan

これまでのところ、これはクロスプラットフォーム、python 2およびpython 3互換の方法のみです。ありがとう。
RJ

9

ここには良い答えがいくつかありますが、堅牢性の低いものもあります。ここに概要があります。

それをしない方法

Pythonやsite-packagesフォルダの場所に依存しないでください。

これらが標準以外の場所に設定されている場合でも、実際に仮想環境にいるわけではありませ。ユーザーは複数のバージョンのPythonをインストールできますが、それらのバージョンは必ずしも期待どおりではありません。

見ないでください:

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

また、の存在venv.venvまたはenvsこれらのパスのいずれかを確認しないでください。これは、より固有の場所を持つ環境では機能しなくなります。たとえば、 Pipenvはその環境の名前としてハッシュ値を使用します。

VIRTUAL_ENV 環境変数

両方とも、環境をアクティブにするときに環境変数virtualenvvenv設定し$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

virtualenvvenvそして予想通り、virtualenv内にインストールされたPython をpyvenvポイントsys.prefixします。

同時に、の元の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仮想環境を使用している場合は、Victoria Stuartの回答を確認してください 。


OPは「方法を教えてください」ではなく、「方法を教えてください」と尋ねています。この答えはやりすぎです。それは質問の精神を超えて、あまりにも多くのバリエーションで答えを難読化します。答えはできるだけシンプルにして、質問に直接答えてください。
Rich Lysakowski PhD

ここでは複数の回答を要約し、特定の状況にどちらが適切かについてアドバイスを提供しています。元の質問は、これらの手法の1つを「最良の」手法として選択するための十分なコンテキストを提供していません-それはそれほど単純ではありません。
florisla

1
sys.base_prefixためのセクションでは、テストがあってはならない:running_in_virtualenv = sys.*base_*prefix != sys.prefix
usonianhorizo​​n

@usonianhorizo​​n本当、ありがとう!
florisla

@florisiaありがとうございます!私は、virtualenvwrapperからアプリケーションデプロイメント用の組み込みvenvに移行中です。あなたの説明で、その方法のテンプレートがわかりました。私はif hasattr(sys, 'real_prefix'):テストのみに依存していたが、それはもはや機能しなかった。
usonianhorizo​​n

8

あなたはそれwhich pythonが仮想環境のものを指しているかどうかを確認することができます。


1
whichWindowsではデフォルトでは使用できません。whereWindowsで代わりに使用するか、whichcraftを使用できます。またはを見てくださいsys.executable。しかし、それでも、より良い方法があります。
florisla

5
  • 2019年11月更新(追加)。

私は定期的に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) $

Update 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年11月]

私の最初の投稿以来、Anaconda venv(そしてPython自体がviz-a-viz仮想環境を進化させてきました)から移動しました。

この問題を再検討して、特定のPython仮想環境(venv)で動作していることをテストするために挿入できるいくつかの更新されたPythonコードを次に示します。

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ベースパスも返し、env変数のチェックが行わないreadthedocsでも機能します):

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

ここにはすでに多くの優れたメソッドが投稿されていますが、もう1つ追加するだけです。

import site
site.getsitepackages()

pipパッケージをインストールした場所を示します。


Pythonが仮想環境内で実行されているかどうかはわかりません。
florisla

@florisla詳しく説明していただけますか?場合はsite.getsitepackages()、システムの一つではないのディレクトリ出力、そしてあなたは、仮想環境にいると推論することができます。
flow2k

Pythonは複数の場所にインストールできます。たとえば、Windowsでは、「システム」PythonとWinPythonディストリビューション、およびCondaベースのPythonをインストールできます。これらはすべて異なるサイトパッケージフォルダーを持っていますが、必ずしもによって作成(または使用)されているわけではありませんvirtualenv
florisla

@florisla良い点-私はこれを(venvであるかどうかにかかわらず)見ただけで、質問が尋ねているものです(私は別の質問に対して同様の回答を書きました)。私はこれがvenvにいるかどうかに関して確実な答えを与えないかもしれませんが、どのPython venvを使用しているか、またはどちらを使用しているかを通知するのに役立つ可能性があることに同意します。
flow2k

-1

それは防弾ではありませんが、UNIX環境のような簡単なテスト

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

私にとってはうまくいきます。それはいくつかの属性の既存のものをテストするより簡単であり、とにかく、あなたはあなたのvenvディレクトリに名前を付けるべきですvenv


-1

Windows OSでは、次のように表示されます。

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

これは古い質問ですが、上記の例が多すぎて複雑すぎます。

シンプルに保つ:(Windows 10のJupyter NotebookまたはPython 3.7.1ターミナル)


import sys
print(sys.executable)```

# example output: >> `C:\Anaconda3\envs\quantecon\python.exe`

OR 
```sys.base_prefix```

# Example output: >> 'C:\\Anaconda3\\envs\\quantecon'

envsそのパスに存在するかどうかを確認するロジックを追加すると、anacondaからvirtualenvまたはに移動したときに機能が停止しますpipenv
florisla

フロリスラ、私が制限内で機能する回答を提供してからほぼ3か月後に、「どうすればいいのか」という回答を提供してくれました(virtualenvとpipenvの間を移動しません)。自分の見た目を良くするために他の人の回答に反対投票するのは悪いスポーツです。
Rich Lysakowski PhD

金持ち、あなたのために働くことは他の人のために働かないかもしれません。オリジナルのポスターではうまくいかないかもしれません。
florisla
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.