2013-03-16 7 views
15

W jaki sposób funkcja bash sprawdza, czy działa w wirtualnym języku Python?Skąd wiadomo, że funkcja powłoki działa w ramach virtualenv?

dwóch podejść, które przychodzą do głowy to:

[[ "$(type -t deactivate)" != function ]]; INVENV=$? 

lub

[[ "x$(which python)" != "x$VIRTUAL_ENV/bin/python" ]]; INVENV=$? 

(Uwaga: chcąc $INVENV być 1 czy jesteśmy wewnątrz virtualenv, a 0 w przeciwnym razie, to co wymusza wcześniejsze testy wstecz.)

Czy jest coś mniej hacky?

+0

Istnieje również 'command -v', wbudowana powłoka. – phk

Odpowiedz

12

Faktycznie, ja po prostu znaleźć podobne pytanie, z którego można łatwo wyprowadzić odpowiedź do tego:

Python: Determine if running inside virtualenv

np skrypt można użyć coś jak

python -c 'import sys; print (sys.real_prefix)' 2>/dev/null && INVENV=1 || INVENV=0 

(Dzięki Christian długo, pokazując w jaki sposób dokonać tej pracy rozwiązanie z Pythonie 3 również.)

EDIT: Tutaj jest bardziej bezpośredni (stąd wyraźniejszy i czystszy) rozwiązanie (biorąc przykład z komentarzem JuanPablo za) :

INVENV=$(python -c 'import sys; print ("1" if hasattr(sys, "real_prefix") else "0")') 
+1

opcjonalne polecenie do sprawdzenia: 'python -c 'import sys; print hasattr (sys, "real_prefix") '' – JuanPablo

+2

Dodaj nawiasy do obsługi importujących sys Pythona 3' python -c'; print (sys.real_prefix) '2>/dev/null && INVENV = 1 || INVENV = 0' –

16
if [[ "$VIRTUAL_ENV" != "" ]] 
then 
    INVENV=1 
else 
    INVENV=0 
fi 
// or shorter if you like: 
[[ "$VIRTUAL_ENV" == "" ]]; INVENV=$? 

EDIT: a @ThiefMaster wymienia w komentarzach, w pewnych warunkach (na przykład, podczas uruchamiania nowej powłoki może - w tmux lub screen - od wewnątrz aktywnego virtualenv) ten test może nie (jednak uruchamianie nowych powłok z poziomu virtualenv również może powodować inne problemy, nie polecam go).

+0

Unikałem tego podejścia, ponieważ miałem sytuacje, w których '$ VIRTUAL_ENV' został ustawiony, ale (z jakiegoś powodu), nie w' $ PATH' ... – kjo

+0

Nie jesteś pewien, co '$ PATH' ma z tym wspólnego? Czy masz na myśli, że chcesz sprawdzić, czy twój bieżący katalog roboczy jest częścią virtualenv? – robertklep

+0

Przepraszam za mój mylący komentarz; jeśli '$ VIRTUAL_ENV' nie znajduje się w' $ PATH', to '' python' plik wykonywalny, który zostanie użyty przez wszystko inne, nie będzie tym w virtualenv. Samo przypisanie wartości do '$ VIRTUAL_ENV' nic nie robi. – kjo

1

Jeśli używasz virtualenvwrappers, są uruchomione skrypty przed/po, które mogą ustawić INVENV dla ciebie.

Albo co zrobić, umieścić następujące informacje w swoim .bashrc i zrobić plik o nazwie .venv w katalogu roboczym (dla Django), tak, że wirtualny env jest automatycznie ładowany podczas CD do katalogu

export PREVPWD=`pwd` 
export PREVENV_PATH= 

handle_virtualenv(){ 
    if [ "$PWD" != "$PREVPWD" ]; then 
     PREVPWD="$PWD"; 
     if [ -n "$PREVENV_PATH" ]; then 
      if [ "`echo "$PWD" | grep -c $PREVENV_PATH`" = "0" ]; then 
       deactivate 
       unalias python 2> /dev/null 
       PREVENV_PATH= 
      fi 
     fi 

     # activate virtualenv dynamically 
     if [ -e "$PWD/.venv" ] && [ "$PWD" != "$PREVENV_PATH" ]; then 
      PREVENV_PATH="$PWD" 
      workon `basename $PWD` 
      if [ -e "manage.py" ]; then 
       alias python='python manage.py shell_plus' 
      fi 
     fi 
    fi 
} 

export PROMPT_COMMAND=handle_virtualenv 
+0

Dzięki za kod. BTW, myślę, że bash zachowuje już 'OLDPWD', czyli to samo, co' PREVPWD' w twoim kodzie. – kjo