Determina se Python è in esecuzione all'interno di virtualenv


272

È possibile determinare se lo script corrente è in esecuzione all'interno di un ambiente virtualenv?


2
Per curiosità, perché vorresti saperlo?
Jorge Leitao,

1
vale a dire essere in grado di scrivere script personalizzati che generano prompt per la shell e si desidera che quel prompt indichi se ci si trova o meno in venv, quindi si desidera essere in grado di rilevarlo da quel codice, meglio senza chiamare strumenti esterni .
Marcin Orlowski,

Risposte:


227

AFAIK il modo più affidabile per verificarlo (e il modo in cui viene utilizzato internamente in virtualenv e in pip) è verificare l'esistenza di sys.real_prefix:

import sys

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

All'interno di un virtualenv, sys.prefixpunta alla directory virtualenv, e sys.real_prefixindica il prefisso "reale" del sistema Python (spesso /usro /usr/localo qualcosa del genere).

Al di fuori di un virtualenv, sys.real_prefixnon dovrebbe esistere.

L'uso della VIRTUAL_ENVvariabile d'ambiente non è affidabile. È impostato dallo activatescript della shell virtualenv , ma un virtualenv può essere utilizzato senza attivazione eseguendo direttamente un eseguibile dalla directory bin/(o Scripts) di virtualenv , nel qual caso $VIRTUAL_ENVnon verrà impostato.


11
Questo non sembra più essere valido in Python 3.
Dan P.

49
Se stai usando virtualenv (github.com/pypa/virtualenv), questa risposta è ugualmente corretta per Python 2 o Python 3. Se stai usando pyvenv ( legacy.python.org/dev/peps/pep-0405 ), un virtualenv -equivalente incorporato in Python 3.3+ (ma non è la stessa cosa di virtualenv), quindi usa sys.base_prefix invece di sys.real_prefix, e sys.base_prefix esiste sempre; fuori da un pyvenv è uguale a sys.prefix.
Carl Meyer,

2
@Kounavi Non credo sia probabile che la versione di Windows abbia alcun impatto. Questa risposta è una parte fondamentale di come funziona virtualenv su qualsiasi piattaforma. È possibile che tu stia usando Python 3 pyvenv, non virtualenv, sul computer Windows 2012? O che qualcosa sta succedendo con il PERCORSO e in realtà non stai eseguendo virtualenv quando pensi di esserlo?
Carl Meyer,

3
One-liner for bash scriptPYTHON_ENV=$(python -c "import sys; sys.stdout.write('1') if hasattr(sys, 'real_prefix') else sys.stdout.write('0')")
Sam Myers,

2
Questa risposta è obsoleta, non sorprende. In particolare, questa risposta restituisce falsi negativi per i casi d'uso comuni. Questo è male. Invece, vedere uno: hroncok 's autorevole aggiornamento rilevare correttamente tutti i non-Anaconda VENVS o Victoria Stuart ' s risposta autorevole rilevare correttamente tutti Anaconda VENVS . ( Tutti i miei voti per chiunque combini queste due risposte. )
Cecil Curry

98

Prova a usare pip -V(nota maiuscola V)

Se stai eseguendo l'env virtuale. mostrerà il percorso verso la posizione dell'ambiente.


Se ti sei spostato virtualenvmolto, è possibile che questo possa fallire o mentirti. Se sta mentendo, puoi farlo find /path/to/venv/ -type f -exec sed -ie "s:/old/path/to/venv:/path/to/venv:g" {} \+. Se fallisce (ho "dati di marshal cattivi") dovrai cancellare i file .pyc find /path/to/venv -type f -name "*.pyc" -exec rm {} \+(non preoccuparti, si ricostruiranno automaticamente).
jeremysprofile,

Ho appena provato questo su Windows 10 con Python 3.7. Stampa la posizione di pip dall'installazione predefinita ...\lib\site-packagesin %PATH%. Quindi restituirà un falso positivo in quel caso.
JamesThomasMoon1979,

72

Questo è un miglioramento della risposta accettata da Carl Meyer . Funziona con virtualenv per Python 3 e 2 e anche per il modulo venv in Python 3:

import sys


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

Il controllo per le sys.real_prefixcopertine virtualenv, l'uguaglianza del non vuoto sys.base_prefixcon le sys.prefixcopertine venv.

Considera uno script che utilizza la funzione in questo modo:

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

E la seguente invocazione:

$ 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
Dato che Python 3.3 non è più tenuto o supportato dalla maggior parte Python 3 quadri e applicazioni, questa funzione ora riduce ad un banale one-liner: def is_venv(): return hasattr(sys, 'real_prefix') or sys.base_prefix != sys.prefix. Sto solo dicendo.
Cecil Curry,

Purtroppo questo non sembra funzionare con gli pipenvambienti virtuali creati.
dragon788,

46

Controlla la $VIRTUAL_ENVvariabile d'ambiente.

La $VIRTUAL_ENVvariabile di ambiente contiene la directory dell'ambiente virtuale quando si trova in un ambiente virtuale attivo.

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

Una volta eseguito deactivate/ abbandonato l'ambiente virtuale, la $VIRTUAL_ENVvariabile verrà cancellata / vuota. Python genererà a KeyErrorperché la variabile di ambiente non era impostata.

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

Questi stessi controlli delle variabili d'ambiente possono ovviamente essere eseguiti anche al di fuori dello script Python, nella shell.


1
Questo funziona sia per virtualenvvirtualenv che per venvvirtualenv.
florisla,

@verboze: come dovrebbe fare, giusto? Un virtualenv disattivato significa che lo script utente non è in esecuzione su uno.
MestreLion,

Questo controlla se un virtualenv è attivato, ma ciò non significa necessariamente che il processo Python in esecuzione provenga da quel virtualenv.
Erb

20

Secondo virtualenv pep su http://www.python.org/dev/peps/pep-0405/#specification puoi semplicemente usare sys.prefix invece os.environ ['VIRTUAL_ENV'].

il sys.real_prefix non esiste nel mio virtualenv e lo stesso con il sys.base_prefix.


8
virtualenv è il progetto autonomo che funziona su qualsiasi versione di Python ( github.com/pypa/virtualenv ). Il PEP a cui ti sei collegato è per pyvenv, che si basa su virtualenv ma è implementato in modo diverso (migliore) ed è integrato in Python 3.3+. Questa domanda riguarda virtualenv, non pyvenv. Hai ragione che in un pyvenv non c'è sys.real_prefix.
Carl Meyer,

5
Un buon modo per rilevare da bash usando questa risposta è eseguire: env |grep VIRTUAL_ENV |wc -l che restituirà un 1 se in un venv o uno 0 in caso contrario.
LISTERINA

3
Se sei in una shell puoi semplicemente usare [[ -n $VIRTUAL_ENV ]] && echo virtualenvo in [[ -z $VIRTUAL_ENV ]] && echo not virtualenvbase alle tue esigenze.
Sei

10

Per verificare se il tuo Virtualenv interno:

import os

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

Puoi anche ottenere più dati sul tuo ambiente:

import sys
import os

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

1
Questo è il miglior approccio multipiattaforma (Windows / Unix).
Adi Unnithan,

Finora, questo è solo compatibile con multipiattaforma, python 2 e python 3. Grazie.
RJ

9

Ci sono molte buone risposte qui e alcune meno robuste. Ecco una panoramica.

Come non farlo

Non fare affidamento sulla posizione di Python o sulla site-packagescartella.

Se questi sono impostati su posizioni non standard, ciò non significa che in realtà ti trovi in ​​un ambiente virtuale. Gli utenti possono avere più di una versione di Python installata e quelli non sono sempre dove ti aspetti che siano.

Evita di guardare:

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

Inoltre, non verificare la presenza di venv, .venvo envsin uno di questi percorsi. Ciò si interromperà per ambienti con una posizione più unica. Ad esempio, Pipenv utilizza i valori hash come nome per i suoi ambienti.

VIRTUAL_ENV variabile d'ambiente

Entrambi virtualenve venvimpostare la variabile di ambiente $VIRTUAL_ENVquando si attiva un ambiente. Vedi PEP 405 .

Puoi leggere questa variabile negli script di shell o usare questo codice Python per determinare se è impostato.

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

Il problema è che funziona solo quando l'ambiente è attivato dallo activatescript della shell.

Puoi avviare gli script dell'ambiente senza attivare l'ambiente , quindi se questo è un problema, devi usare un metodo diverso.

sys.base_prefix

virtualenv, venvE pyvenvpunto sys.prefixal Python installata all'interno del virtualenv come ci si aspetterebbe.

Allo stesso tempo, viene reso disponibile anche il valore originale di .sys.prefixsys.base_prefix

Possiamo usarlo per rilevare se siamo in 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

Ricaderci: sys.real_prefix

Ora attenzione, virtualenvprima che la versione 20 non fosse impostata sys.base_prefixma sys.real_prefixinvece fosse impostata .

Per sicurezza, controlla entrambi come suggerito nella risposta di 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

Se stai utilizzando ambienti virtuali Anaconda, controlla la risposta di Victoria Stuart .


L'OP chiede "Come faccio?", Non "Come NON?" Questa risposta è eccessiva. Va oltre lo spirito della domanda e offusca la risposta con troppe variazioni. Ti preghiamo di mantenere le risposte il più semplice possibile e rispondere direttamente alla domanda.
Rich Lysakowski PhD,

Sto riassumendo le risposte multiple qui e sto fornendo consigli su quale potrebbe essere giusto per circostanze specifiche. La domanda originale non fornisce un contesto sufficiente per selezionare una di queste tecniche come la "migliore" - semplicemente non è così semplice.
florisla,

1
Nella sezione per sys.base_prefix, il test non dovrebbe essere:running_in_virtualenv = sys.*base_*prefix != sys.prefix
usonianhorizon

@usonianhorizon Vero, grazie!
florisla,

Grazie @Florisia! Sono in fase di transizione da virtualenvwrapper a venv integrato per la distribuzione dell'applicazione e la tua spiegazione mi ha fornito il modello su come farlo. Avevo fatto affidamento solo sul if hasattr(sys, 'real_prefix'):test, che non funzionava più.
usonianhorizon,

8

Puoi fare which pythone vedere se punta a quello in ambiente virtuale.


1
whichnon è disponibile per impostazione predefinita su Windows. È possibile utilizzare whereinvece su Windows o utilizzare whocraft . O guarda sys.executable. Tuttavia, ci sono metodi migliori.
Florisla,

5
  • Aggiornato novembre 2019 (allegato).

Uso abitualmente diversi ambienti virtuali (venv) installati su Anaconda. Questo frammento di codice / esempi consente di determinare se ci si trova in un venv (o nell'ambiente di sistema) e di richiedere anche un venv specifico per lo script.

Aggiungi allo script Python (frammento di codice):

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

Esempio:

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

Aggiornamento 1 - utilizzare negli script bash:

È inoltre possibile utilizzare questo approccio negli script bash (ad esempio, quelli che devono essere eseguiti in un ambiente virtuale specifico). Esempio (aggiunto allo script 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

Aggiornamento 2 [nov 2019]

Dal mio post originale sono passato da Anaconda Venv (e lo stesso Python ha evoluto ambienti virtuali Viz -a-Viz ).

Riesaminando questo problema, ecco un codice Python aggiornato che è possibile inserire per verificare che si stia operando in un ambiente virtuale Python specifico (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()

Ecco qualche codice esplicativo.

[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

Il modo più semplice è semplicemente eseguire which python:, se sei in virtualenv, punterà al suo pitone anziché a quello globale


1
Non penso che questo in realtà risponda alla domanda (che è preoccupato per lo "script corrente"). Tuttavia, questo risponde alla mia domanda particolare, "come faccio a sapere se mi trovo in un ambiente virtuale dalla riga di comando".
ukrutt,

1

(a cura) L'ho trovato in questo modo, cosa ne pensi? (restituisce anche il percorso di base venv e funziona anche per readthedocs dove il controllo della variabile env non lo fa):

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

Ci sono già molti ottimi metodi pubblicati qui, ma aggiungo solo uno in più:

import site
site.getsitepackages()

ti dice dove sono pipinstallati i pacchetti.


Questo non dice se Python è in esecuzione all'interno di un ambiente virtuale o meno.
florisla,

@florisla Potresti elaborare? Se site.getsitepackages()genera una directory che non è quella di sistema, puoi dedurre che ti trovi in ​​un ambiente virtuale.
flow2k

È possibile installare Python in più posizioni. Ad esempio, su Windows è possibile installare un 'sistema' Python e una distribuzione WinPython più un Python basato su Conda. Questi hanno tutti cartelle di pacchetti di siti diversi ma non sono necessariamente creati da (o utilizzati in) a virtualenv.
florisla,

@florisla Un buon punto: ho appena visto questo (venv o no) è quello che la domanda sta facendo (avevo scritto una risposta simile per un'altra domanda). Sono d'accordo che questo potrebbe non dare la risposta infallibile sul fatto che tu sia in una venv o meno, ma potrebbe aiutarti a dirti quale Python o quale venvstai usando.
flow2k,

-1

Non è a prova di proiettile ma per ambienti UNIX test semplici come

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

funziona benissimo per me. È più semplice quindi testare l'esistenza di alcuni attributi e, comunque, dovresti dare un nome alla tua directory venv venv.


-1

Nel sistema operativo Windows vedi qualcosa del genere:

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

Le parentesi indicano che in realtà ci si trova nell'ambiente virtuale chiamato "virtualEnvName".


Io e te possiamo leggere "virtualEnvName" bene. Ma la domanda è: come un modulo Python può leggere questo.
florisla,

-1

Una potenziale soluzione è:

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

Nel mio caso volevo solo scoprire se potevo installare gli oggetti con pip così com'è. Anche se potrebbe non essere la soluzione giusta per tutti i casi, considera semplicemente la verifica se disponi delle autorizzazioni di scrittura per l'ubicazione dell'eseguibile Python.

Nota: funziona in tutte le versioni di Python, ma restituisce anche Truese si esegue il sistema Python con sudo. Ecco un potenziale caso d'uso:

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

Questa è una vecchia domanda, ma troppi esempi sopra sono troppo complicati.

Keep It Simple: (nel terminale Jupyter Notebook o Python 3.7.1 su 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'

Se aggiungi la logica per verificare la presenza envsin quel percorso, questo smetterà di funzionare quando passi da anaconda a virtualenvo pipenv.
florisla,

Florisla, hai fornito la tua risposta "Come non farlo" quasi 3 mesi dopo che ho fornito una risposta che funziona per me entro certi limiti (non mi muovo tra virtualenv e pipenv). È un brutto sport sottovalutare le risposte degli altri per migliorare il proprio aspetto.
Rich Lysakowski PhD,

Ricco, ciò che funziona per te potrebbe non funzionare per altre persone. Potrebbe non funzionare nemmeno per il poster originale.
florisla,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.