Tentukan apakah Python berjalan di dalam virtualenv

272

Apakah mungkin untuk menentukan apakah skrip saat ini berjalan di dalam lingkungan virtualenv?

miracle2k
sumber
2
Karena penasaran, mengapa Anda ingin tahu itu?
Jorge Leitao
1
yaitu untuk dapat menulis skrip khusus yang menghasilkan prompt untuk shell Anda dan Anda ingin prompt itu menunjukkan apakah Anda berada di venv atau tidak, jadi Anda ingin dapat mendeteksi itu dari dalam kode itu, sebaiknya tanpa memanggil alat eksternal .
Marcin Orlowski

Jawaban:

227

AFAIK cara yang paling dapat diandalkan untuk memeriksa ini (dan cara yang digunakan secara internal di virtualenv dan di pip) adalah untuk memeriksa keberadaan sys.real_prefix:

import sys

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

Di dalam virtualenv, sys.prefixmenunjuk ke direktori virtualenv, dan sys.real_prefixmenunjuk ke awalan "nyata" dari sistem Python (sering /usratau /usr/localatau semacamnya).

Di luar virtualenv, sys.real_prefixseharusnya tidak ada.

Menggunakan VIRTUAL_ENVvariabel lingkungan tidak dapat diandalkan. Ini diatur oleh activateskrip virtualenv shell, tetapi virtualenv dapat digunakan tanpa aktivasi dengan langsung menjalankan executable dari direktori virtualenv bin/(atau Scripts), dalam hal $VIRTUAL_ENVini tidak akan ditetapkan.

Carl Meyer
sumber
11
Ini sepertinya tidak berlaku lagi di Python 3.
Dan P.
49
Jika Anda menggunakan virtualenv (github.com/pypa/virtualenv), jawaban ini sama benarnya untuk Python 2 atau Python 3. Jika Anda menggunakan pyvenv ( legacy.python.org/dev/peps/pep-0405 ), sebuah virtualenv -setara dibangun ke Python 3.3+ (tapi tidak sama dengan virtualenv), maka ia menggunakan sys.base_prefix bukan sys.real_prefix, dan sys.base_prefix selalu ada; di luar pyvenv sama dengan sys.prefix.
Carl Meyer
2
@ Kounavi Saya tidak berpikir kemungkinan versi Windows akan berdampak apa pun. Jawaban ini adalah bagian inti dari bagaimana virtualenv bekerja pada platform apa pun. Apakah mungkin Anda menggunakan Python 3 pyvenv, bukan virtualenv, pada mesin Windows 2012? Atau ada sesuatu yang terjadi dengan PATH dan Anda sebenarnya tidak berjalan di virtualenv ketika Anda pikir Anda?
Carl Meyer
3
One-liner untuk skrip bashPYTHON_ENV=$(python -c "import sys; sys.stdout.write('1') if hasattr(sys, 'real_prefix') else sys.stdout.write('0')")
Sam Myers
2
Jawaban ini sudah usang, tidak mengejutkan. Secara khusus, jawaban ini mengembalikan negatif palsu untuk kasus penggunaan umum. Itu buruk. Sebaliknya, melihat baik: hroncok 's pembaruan otoritatif benar mendeteksi semua non-Anaconda venvs atau Victoria Stuart ' s jawaban otoritatif benar mendeteksi semua Anaconda venvs . ( Semua upvotes saya untuk siapa pun yang menggabungkan dua jawaban itu. )
Cecil Curry
97

Coba gunakan pip -V(perhatikan modal V)

Jika Anda menjalankan env virtual. itu akan menunjukkan jalur ke lokasi env.

loki l
sumber
Jika Anda sering berpindah-pindah virtualenv, ada kemungkinan ini bisa gagal atau berbohong kepada Anda. Jika itu bohong, Anda bisa melakukannya find /path/to/venv/ -type f -exec sed -ie "s:/old/path/to/venv:/path/to/venv:g" {} \+. Jika gagal (saya mendapat "data marshal buruk") Anda harus menghapus file .pyc dengan find /path/to/venv -type f -name "*.pyc" -exec rm {} \+(jangan khawatir, mereka akan membangun kembali secara otomatis).
jeremysprofile
Saya baru saja menguji ini pada Windows 10 dengan Python 3.7. Ini mencetak lokasi pip dari instalasi default ...\lib\site-packagesdi %PATH%. Jadi itu akan mengembalikan false positive dalam kasus itu.
JamesThomasMoon1979
71

Ini adalah peningkatan dari jawaban yang diterima oleh Carl Meyer . Ia bekerja dengan virtualenv untuk Python 3 dan 2 dan juga untuk modul venv di Python 3:

import sys


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

Pemeriksaan untuk sys.real_prefixpenutup virtualenv, persamaan non-kosong sys.base_prefixdengan sys.prefixpenutup venv.

Pertimbangkan skrip yang menggunakan fungsi seperti ini:

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

Dan doa berikut:

$ 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
sumber
4
Sejak Python 3.3 adalah tidak lagi dipertahankan atau didukung oleh sebagian besar Python 3 kerangka kerja dan aplikasi, fungsi ini sekarang mengurangi untuk satu-kapal sepele: def is_venv(): return hasattr(sys, 'real_prefix') or sys.base_prefix != sys.prefix. Katakan saja.
Cecil Curry
Sayangnya ini tidak berfungsi dengan pipenvlingkungan virtual yang dibuat.
dragon788
46

Periksa $VIRTUAL_ENVvariabel lingkungan.

The $VIRTUAL_ENVvariabel lingkungan berisi direktori lingkungan virtual ketika dalam lingkungan virtual yang aktif.

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

Setelah Anda menjalankan deactivate/ meninggalkan lingkungan virtual, $VIRTUAL_ENVvariabel akan dihapus / kosong. Python akan menaikkan a KeyErrorkarena variabel lingkungan tidak disetel.

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

Pemeriksaan variabel lingkungan yang sama ini tentu saja dapat juga dilakukan di luar skrip Python, di shell.

MrHetii
sumber
1
Ini berfungsi baik untuk virtualenvvirtualenv dan venvvirtualenv.
florisla
@verboze: seperti yang seharusnya dilakukan, kan? Virtualenv yang dinonaktifkan berarti skrip pengguna tidak berjalan pada satu.
MestreLion
Ini memeriksa apakah virtualenv diaktifkan, tetapi itu tidak berarti bahwa proses Python yang berjalan adalah dari virtualenv itu.
erb
20

Menurut virtualenv pep di http://www.python.org/dev/peps/pep-0405/#specification, Anda bisa menggunakan sys.prefix sebagai ganti os.environ ['VIRTUAL_ENV'].

sys.real_prefix tidak ada di virtualenv saya dan sama dengan sys.base_prefix.

Kronos
sumber
8
virtualenv adalah proyek mandiri yang berfungsi pada semua versi Python ( github.com/pypa/virtualenv ). PEP yang Anda tautkan adalah untuk pyvenv, yang didasarkan pada virtualenv tetapi diimplementasikan secara berbeda (lebih baik) dan terintegrasi dengan Python 3.3+. Pertanyaan ini tentang virtualenv, bukan pyvenv. Anda benar bahwa dalam pyvenv tidak ada sys.real_prefix.
Carl Meyer
5
Cara yang bagus untuk mendeteksi dari bash menggunakan jawaban ini adalah menjalankan: env |grep VIRTUAL_ENV |wc -l yang akan mengembalikan 1 jika dalam venv atau 0 jika tidak.
LISTERINE
3
Jika Anda menggunakan shell, Anda dapat menggunakan [[ -n $VIRTUAL_ENV ]] && echo virtualenvatau [[ -z $VIRTUAL_ENV ]] && echo not virtualenvbergantung pada kebutuhan Anda.
Enam
9

Untuk memeriksa apakah bagian dalam Virtualenv Anda:

import os

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

Anda juga dapat memperoleh lebih banyak data tentang lingkungan Anda:

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
sumber
1
Ini adalah pendekatan lintas platform (Windows / Unix) terbaik.
Adi Unnithan
Sejauh ini, ini hanya cross platform, python 2 dan python 3 yang kompatibel. Terima kasih.
RJ
9

Ada beberapa jawaban bagus di sini, dan beberapa di antaranya kurang kuat. Inilah ikhtisar.

Bagaimana tidak melakukannya

Jangan bergantung pada lokasi Python atau site-packages folder.

Jika ini disetel ke lokasi non-standar, itu tidak berarti Anda sebenarnya berada di lingkungan virtual. Pengguna dapat menginstal lebih dari satu versi Python, dan itu tidak selalu sesuai dengan yang Anda harapkan.

Hindari melihat:

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

Juga, jangan periksa keberadaan venv, .venvatau envsdi jalur mana pun. Ini akan merusak lingkungan dengan lokasi yang lebih unik. Misalnya, Pipenv menggunakan nilai hash sebagai nama untuk lingkungannya.

VIRTUAL_ENV variabel lingkungan

Keduanya virtualenvdan venvmengatur variabel lingkungan $VIRTUAL_ENVsaat mengaktifkan suatu lingkungan. Lihat PEP 405 .

Anda dapat membaca variabel ini dalam skrip shell, atau menggunakan kode Python ini untuk menentukan apakah sudah disetel.

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

Masalahnya adalah, ini hanya berfungsi ketika lingkungan diaktifkan oleh activateskrip shell.

Anda dapat memulai skrip lingkungan tanpa mengaktifkan lingkungan , jadi jika itu merupakan masalah, Anda harus menggunakan metode yang berbeda.

sys.base_prefix

virtualenv, venvdan pyvenvarahkan sys.prefixke Python yang terinstal di dalam virtualenv seperti yang Anda harapkan.

Pada saat bersamaan, asli nilai sys.prefixjuga dibuat tersedia sebagai sys.base_prefix.

Kita bisa menggunakannya untuk mendeteksi jika kita berada di 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

Fallback: sys.real_prefix

Sekarang hati-hati, virtualenvsebelum versi 20 tidak diatursys.base_prefix tetapi diatursys.real_prefix sebagai gantinya.

Agar aman, periksa keduanya seperti yang disarankan dalam jawaban 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

Jika Anda menggunakan lingkungan virtual Anaconda, periksa jawaban Victoria Stuart .

florisla
sumber
OP bertanya "Bagaimana saya?", Bukan "Bagaimana TIDAK?" Jawaban ini berlebihan. Itu melampaui semangat pertanyaan dan mengaburkan jawabannya dengan terlalu banyak variasi. Harap simpan jawaban Anda sesederhana mungkin dan jawab pertanyaan itu secara langsung.
Rich Lysakowski PhD
Saya merangkum beberapa jawaban di sini, dan memberikan saran yang mana yang tepat untuk situasi tertentu. Pertanyaan asli tidak menyediakan konteks yang cukup untuk memilih salah satu dari teknik ini sebagai yang 'terbaik' - hanya saja tidak sesederhana itu.
florisla
1
Di bagian untuk sys.base_prefix, tes seharusnya tidak menjadi:running_in_virtualenv = sys.*base_*prefix != sys.prefix
usonianhorizon
@usonianhorizon Benar, terima kasih!
florisla
Terima kasih, @florisia! Saya sedang dalam proses transisi dari virtualenvwrapper ke built-in venv untuk penerapan aplikasi, dan penjelasan Anda memberi saya templat tentang cara melakukannya. Saya hanya mengandalkan if hasattr(sys, 'real_prefix'):tes, yang tidak lagi berhasil.
usonianhorizon
8

Anda dapat melakukan which pythondan melihat apakah ini menunjuk ke yang ada di virtual env.

kunrazor
sumber
1
whichtidak tersedia secara default di Windows. Anda bisa menggunakan wherehanya pada Windows, atau mempekerjakan whichcraft . Atau lihat sys.executable. Tapi tetap saja, ada metode yang lebih baik.
florisla
5
  • Diperbarui Nov 2019 (ditambahkan).

Saya secara rutin menggunakan beberapa lingkungan virtual yang diinstal Anaconda (venv). Cuplikan kode / contoh ini memungkinkan Anda untuk menentukan apakah Anda berada di venv (atau lingkungan sistem Anda), dan juga membutuhkan venv spesifik untuk skrip Anda.

Tambahkan ke skrip Python (cuplikan kode):

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

Contoh:

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

Perbarui 1 - gunakan dalam skrip bash:

Anda juga dapat menggunakan pendekatan ini dalam skrip bash (mis., Yang harus dijalankan dalam lingkungan virtual tertentu). Contoh (ditambahkan ke skrip 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

Pembaruan 2 [Nov 2019]

Sejak posting asli saya, saya sudah pindah dari Anaconda venv (dan Python itu sendiri telah berevolusi viz-a-viz lingkungan virtual).

Memeriksa ulang masalah ini, berikut adalah beberapa kode Python yang diperbarui yang dapat Anda masukkan untuk menguji apakah Anda beroperasi di lingkungan virtual (vv) Python tertentu.

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

Berikut ini beberapa kode penjelasan.

[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
sumber
3

Cara termudah adalah dengan hanya menjalankan which python:, jika Anda berada dalam virtualenv itu akan menunjuk ke python bukan global

Silvio Biasiol
sumber
1
Saya tidak berpikir ini benar-benar menjawab pertanyaan (yang berkaitan dengan "skrip saat ini"). Namun ini menjawab pertanyaan khusus saya, "bagaimana saya mencari tahu jika saya berada di lingkungan virtual dari baris perintah."
ukrutt
1

(diedit) Saya menemukan cara itu, bagaimana menurut Anda? (itu juga mengembalikan jalur dasar venv dan bekerja bahkan untuk readthedocs di mana memeriksa variabel env tidak):

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'] + '/../')

sumber
0

Ada banyak metode hebat yang sudah diposting di sini, tetapi hanya menambahkan satu lagi:

import site
site.getsitepackages()

memberitahu Anda di mana pipmenginstal paket.

flow2k
sumber
Ini tidak memberi tahu apakah Python berjalan di dalam lingkungan virtual atau tidak.
florisla
@florisla Bisakah Anda menguraikan? Jika site.getsitepackages()menampilkan direktori yang bukan sistem, maka Anda dapat menyimpulkan bahwa Anda berada di lingkungan virtual.
flow2k
Anda dapat menginstal Python di banyak lokasi. Misalnya, pada Windows Anda dapat menginstal Python 'sistem' dan distribusi WinPython plus Python berbasis Conda. Ini semua memiliki folder paket situs yang berbeda tetapi tidak harus dibuat oleh (atau digunakan dalam) a virtualenv.
florisla
@florisla Poin bagus - Saya baru saja melihat ini (venv or not) adalah pertanyaan yang diajukan (saya telah menulis jawaban yang sama untuk pertanyaan lain). Saya setuju ini mungkin tidak memberikan jawaban pasti apakah Anda berada di venv atau tidak, tetapi dapat membantu memberi tahu Anda Python atau yang venvAnda gunakan.
flow2k
-1

Ini bukan anti peluru tetapi untuk lingkungan UNIX seperti tes sederhana

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

bekerja bagus untukku. Lebih sederhana daripada menguji ada beberapa atribut dan, bagaimanapun, Anda harus memberi nama direktori venv Anda venv.

Mat
sumber
-1

Di OS windows Anda melihat sesuatu seperti ini:

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

Tanda kurung berarti bahwa Anda sebenarnya berada di lingkungan virtual yang disebut "virtualEnvName".

getleft
sumber
Anda dan saya dapat membaca 'virtualEnvName' dengan baik. Tetapi pertanyaannya adalah, bagaimana modul Python dapat membaca ini.
florisla
-1

Sebuah potensi solusi adalah:

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

Dalam kasus saya, saya benar-benar hanya ingin mendeteksi apakah saya dapat menginstal item dengan pip apa adanya. Meskipun ini mungkin bukan solusi yang tepat untuk semua kasus, pertimbangkan untuk memeriksa apakah Anda memiliki izin menulis untuk lokasi eksekusi Python.

Catatan: ini berfungsi di semua versi Python, tetapi juga kembali Truejika Anda menjalankan sistem Python sudo. Berikut ini adalah kasus penggunaan potensial:

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
sumber
-1

Ini adalah pertanyaan lama, tetapi terlalu banyak contoh di atas terlalu rumit.

Keep It Simple: (dalam terminal Jupyter Notebook atau Python 3.7.1 pada 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'
Rich Lysakowski PhD
sumber
Jika Anda menambahkan logika untuk memeriksa keberadaan envsdi jalur itu, ini akan berhenti berfungsi ketika Anda berpindah dari anaconda ke virtualenvatau pipenv.
florisla
Florisla, Anda memberikan jawaban Anda "Bagaimana tidak melakukannya" hampir 3 bulan setelah saya memberikan jawaban yang bekerja untuk saya dalam batas (saya tidak bergerak antara virtualenv dan pipenv). Adalah olahraga yang buruk untuk menurunkan nilai jawaban orang lain agar penampilan Anda lebih baik.
Rich Lysakowski PhD
Kaya, apa yang berhasil untuk Anda mungkin tidak bekerja untuk orang lain. Bahkan mungkin tidak berfungsi untuk poster aslinya.
florisla