Czy źle jest mieć mój katalog virtualenv w moim repozytorium git?

285

Zastanawiam się nad umieszczeniem virtualenv dla aplikacji internetowej Django, którą tworzę w moim repozytorium git dla aplikacji. Wygląda na to, że prosty sposób na wdrożenie jest prosty i łatwy. Czy jest jakiś powód, dla którego nie powinienem tego robić?

Lyle Pratt
źródło

Odpowiedzi:

302

Używam, pip freezeaby pobrać potrzebne mi pakiety requirements.txti dodać je do mojego repozytorium. Próbowałem wymyślić sposób, w jaki chcesz przechowywać całą virtualenv, ale nie mogłem.

RyanBrady
źródło
81
Możesz zaoszczędzić niepotrzebne miejsce w repozytorium i nadal wdrożyć na nowym serwerze za pomocą jednego polecenia: virtualenv --no-site-packages --dystrybucja .env && source .env / bin / aktywuj && pip install -r wymagania.txt
RyanBrady
2
Dam ci odpowiedź na to pytanie, ponieważ jest to prawdopodobnie „najlepsza praktyka”, a ty ją zaoferowałeś jako pierwszy. Zdecydowanie napotkałem niektóre problemy, o których wszyscy wspominali. Szacuję, że daję sobie kolejny dzień na bałagan, zanim zrobię to, co sugerowaliście przez cały czas, i użyję pipa i pliku wymagań. Dzięki za pomoc!
Lyle Pratt,
11
Jeśli, powiedzmy pip install mysql-python, na komputerze 64-bitowym, a następnie ktoś z maszyną 32-bitową spróbuje go użyć, to nie będzie działać. Wykorzystuje moduł C, podobnie jak wiele modułów Pythona, w celu zwiększenia wydajności. Wyobrażam sobie, że Windows-> Linux również nie działałby.
Matt Williamson,
7
tylko uwaga: w przeszłości trochę nam się przydarzyło, ponieważ biblioteki stają się niedostępne dla pipa (wersja zbyt stara), co wymusza aktualizację, gdy strona nie działa. więc ... nigdy pip freezewięcej nie będę na tym polegać . Problem polega na tym, że podczas wymuszonego ponownego wdrożenia nikt nie płaci za to, a za uaktualnienia pośrednie (konserwacja zgodnie z „najlepszymi praktykami”) nikt też tego nie robi.
KONTRAKT MÓWI, ŻE PRAWO
5
Uwaga do komentarza @RayanBrady: Opcje --distributei --setuptoolssą teraz niedostępne . (rozpowszechnianie, to był rozwidlenie setuptools zostało scalone dawno temu). --no-site-packagesjest DEPRECATED, jest to teraz domyślne zachowanie
JackNova
49

Przechowywanie katalogu virtualenv w git pozwoli, jak zauważyłeś, wdrożyć całą aplikację po prostu wykonując klon git (oraz instalując i konfigurując Apache / mod_wsgi). Jednym potencjalnie istotnym problemem związanym z tym podejściem jest to, że w Linuksie pełna ścieżka jest zakodowana na stałe w skryptach aktywujących venv, django-admin.py, easy_install i pip. Oznacza to, że Twój virtualenv nie będzie w pełni działał, jeśli chcesz użyć innej ścieżki, na przykład do uruchomienia wielu wirtualnych hostów na tym samym serwerze. Wydaje mi się, że witryna może faktycznie działać z nieprawidłowymi ścieżkami w tych plikach, ale przy następnej próbie uruchomienia pipa wystąpiłyby problemy.

Rozwiązaniem, które już podano, jest przechowywanie wystarczającej ilości informacji w git, aby podczas wdrażania można było utworzyć virtualenv i wykonać niezbędne instalacje pip. Zazwyczaj ludzie biegają pip freezepo listę, a następnie przechowują ją w pliku o nazwie wymagania.txt. Można go załadować pip install -r requirements.txt. RyanBrady pokazał już, jak można napisać instrukcje wdrażania w jednym wierszu:

# before 15.1.0
virtualenv --no-site-packages --distribute .env &&\
    source .env/bin/activate &&\
    pip install -r requirements.txt

# after deprecation of some arguments in 15.1.0
virtualenv .env && source .env/bin/activate && pip install -r requirements.txt

Osobiście po prostu umieszczam je w skrypcie powłoki, który uruchamiam po wykonaniu git clone lub git pull.

Przechowywanie katalogu virtualenv sprawia, że ​​nieco trudniej jest obsługiwać aktualizacje pip, ponieważ będziesz musiał ręcznie dodawać / usuwać i zatwierdzać pliki wynikające z aktualizacji. Za pomocą pliku wymagania.txt wystarczy zmienić odpowiednie wiersze w pliku wymagania.txt i uruchomić ponownie pip install -r requirements.txt. Jak już wspomniano, zmniejsza to również „spam spam”.

David Sickmiller
źródło
4
Zauważ, że --distribute jest teraz przestarzałe (przynajmniej w 15.1.0): --distribute DEPRECATED. Retained only for backward compatibility. This option has no effect.
AnthonyC
1
--no-site-packagesjest również przestarzałe w 15.1.0, ponieważ jest to teraz ustawienie domyślne.
cjs
35

Robiłem to samo, dopóki nie zacząłem używać bibliotek, które są kompilowane inaczej w zależności od środowiska, takiego jak PyCrypto. Mój Mac PyCrypto nie działa na Cygwin nie działa na Ubuntu.

Zarządzanie repozytorium staje się kompletnym koszmarem.

Tak czy inaczej, łatwiej mi było zarządzać zamrożeniem pliku pip i plikiem wymagań niż mieć to wszystko w git. Jest to również czystsze, ponieważ możesz uniknąć spamowania dla tysięcy plików, gdy biblioteki te są aktualizowane ...

Yuji „Tomita” Tomita
źródło
Hmm Na pewno nie będę miał problemów z kompilacją różnych rzeczy w różnych środowiskach. Myślę, że prawdopodobnie nie warto tego robić, aby uniknąć spamowania.
Lyle Pratt,
@LylePratt: Myślę, że wręcz przeciwnie: lepiej nie uwzględniać całego virtualenv w repozytorium, aby uniknąć problemów z posiadaniem tak doskonałych narzędzi jak PyCrypto lub PIL.
Tadeck,
17

Myślę, że jednym z głównych problemów jest to, że virtualenv może nie być używany przez innych ludzi. Powodem jest to, że zawsze używa ścieżek bezwzględnych. Więc jeśli na przykład virtualenv był w /home/lyle/myenv/nim, założy to samo dla wszystkich innych osób korzystających z tego repozytorium (musi to być dokładnie ta sama ścieżka bezwzględna). Nie możesz zakładać, że ludzie używają tej samej struktury katalogów co ty.

Lepszą praktyką jest to, że każdy tworzy własne środowisko (z wirtualnym wirusem lub bez niego) i instaluje tam biblioteki. To sprawia, że ​​kod jest bardziej użyteczny na różnych platformach (Linux / Windows / Mac), również dlatego, że virtualenv jest zainstalowany na każdej z nich inaczej.

Torsten Engelbrecht
źródło
Jest to słuszne, dlaczego utrzymywanie virtualenv w SCM jest złym pomysłem, ale warto rozważyć coś takiego jak sugestia @ RJBrady lub zdarzenie w skrypcie bootstrap.py , ponieważ pewne sposoby na odtworzenie tego samego środowiska na różnych komputerach to poważna potrzeba podczas pracy z innymi ludźmi.
ig0774,
Nie jestem pewien, czy problem, o którym wspomniałeś, byłby dokładnie problemem w mojej sytuacji. Moja aplikacja Django zawiera plik .wsgi, który określa położenie virtualenv względem jego położenia (2 katalogi w górę „../../env”). Zatem w moim scenariuszu problem z absolutną ścieżką nie powinien mieć negatywnego wpływu na mnie ... prawda?
Lyle Pratt,
Jeśli uruchamiasz aplikację zawsze przy użyciu WSGI, możesz to zrobić. Jeśli użyjesz serwera programistycznego (przez manage.py), na pewno napotkasz problemy.
Torsten Engelbrecht
3

Korzystam z odpowiedzi Davida Sickmillera z nieco większą automatyzacją. Tworzę (niewykonywalny) plik na najwyższym poziomie mojego projektu o nazwie activateo następującej treści:

[ -n "$BASH_SOURCE" ] \
    || { echo 1>&2 "source (.) this with Bash."; exit 2; }
(
    cd "$(dirname "$BASH_SOURCE")"
    [ -d .build/virtualenv ] || {
        virtualenv .build/virtualenv
        . .build/virtualenv/bin/activate
        pip install -r requirements.txt
    }
)
. "$(dirname "$BASH_SOURCE")/.build/virtualenv/bin/activate"

(Zgodnie z odpowiedzią Davida zakłada się, że robisz to, pip freeze > requirements.txtaby aktualizować listę wymagań).

Powyższe daje ogólny pomysł; faktyczny skrypt aktywacyjny ( dokumentacja ), którego zwykle używam, jest nieco bardziej wyrafinowany, oferując -qopcję (cichą), pythongdy python3jest niedostępna itp.

Można to następnie uzyskać z dowolnego bieżącego katalogu roboczego i odpowiednio się aktywuje, w razie potrzeby najpierw konfigurując środowisko wirtualne. Mój skrypt testowy najwyższego poziomu zwykle ma kod wzdłuż tych linii, dzięki czemu można go uruchomić bez konieczności aktywacji przez programistę:

cd "$(dirname "$0")"
[[ $VIRTUAL_ENV = $(pwd -P) ]] || . ./activate

Pozyskiwanie ./activatenie activatejest tutaj ważne, ponieważ ten drugi znajdzie activatena twojej ścieżce inne, zanim znajdzie je w bieżącym katalogu.

cjs
źródło
Uwielbiam to podejście! Brzmi bardzo rozsądnie, dziękuję za udostępnienie.
Esolitos
Musiałem zmienić pierwszy wiersz, aby [[ $_ != $0 ]] || { echo 1>&2 "source (.) this script with Bash."; exit 2; }wykryć, czy skrypt jest wykonywany w przeciwieństwie do źródła
Chris Snow,
3

Włączanie repozytoriów w zależności od środowiska lub ustawienia nie jest dobrym pomysłem, ponieważ jednym z kluczowych aspektów korzystania z repozytorium jest dzielenie się nim z innymi programistami. Oto jak skonfigurowałbym swoje środowisko programistyczne na komputerze z systemem Windows (powiedzmy Win10).

  1. Otwórz Pycharm i na pierwszej stronie wybierz wypisanie projektu ze swojego Systemu Kontroli Źródła (w moim przypadku używam github)

  2. W Pycharm przejdź do ustawień i wybierz „Project Interpreter” i wybierz opcję dodania nowego środowiska wirtualnego, które możesz nazwać „venv”.

  3. Wybierz podstawowy interpreter Pythona, który znajduje się w C: \ Users {użytkownik} \ AppData \ Local \ Programs \ Python \ Python36 (upewnij się, że wybierasz odpowiednią wersję Pythona w oparciu o to, co zainstalowałeś)

  4. Zauważ, że Pycharm utworzy nowe środowisko wirtualne i skopiuje pliki binarne Pythona i wymagane biblioteki w folderze venv w folderze projektu.

  5. Pozwól Pycharmowi zakończyć skanowanie, ponieważ musi odbudować / odświeżyć szkielet projektu

  6. wykluczenie folderu venv od interakcji (git dodać venv \ do .gitignore plik w folderze projektu)

Premia: Jeśli chcesz, aby ludzie łatwo (cóż, prawie łatwo) instalowali wszystkie biblioteki, których potrzebuje twoje oprogramowanie, możesz użyć

pip freeze > requirements.txt

i umieść instrukcję na swoim git, aby ludzie mogli użyć następującego polecenia, aby pobrać wszystkie wymagane biblioteki na raz.

pip install -r requirements.txt 
William Pourmajidi
źródło
2

Jeśli wiesz, na jakich systemach operacyjnych będzie działała twoja aplikacja, utworzę jedną virtualenv dla każdego systemu i dołączę ją do mojego repozytorium. Następnie sprawiłbym, że moja aplikacja wykryłaby system, na którym działa, i użyłaby odpowiedniego virtualenv.

System można np. Zidentyfikować za pomocą modułu platformy .

W rzeczywistości to właśnie robię z aplikacją wewnętrzną, którą napisałem i do której mogę szybko dodać virtualenv nowego systemu w razie potrzeby. W ten sposób nie muszę polegać na tym, że pip będzie mógł pomyślnie pobrać oprogramowanie, którego wymaga moja aplikacja. Nie będę też musiał się martwić kompilacją np. Psycopg2, którego używam.

Jeśli nie wiesz, na którym systemie operacyjnym może działać Twoja aplikacja, prawdopodobnie lepiej będzie, pip freezejak sugerują to inne odpowiedzi tutaj.

Fredrik
źródło
0

Myślę, że najlepiej jest zainstalować środowisko wirtualne w ścieżce w folderze repozytorium, być może lepiej jest użyć podkatalogu poświęconego środowisku (przypadkowo usunąłem cały projekt podczas wymuszania instalacji środowiska wirtualnego w katalogu głównym repozytorium folder, dobrze, że miałem projekt zapisany w najnowszej wersji w Github).

Zarówno automatyczny instalator, jak i dokumentacja powinny wskazywać ścieżkę virtualenv jako ścieżkę względną, dzięki czemu nie napotkasz problemów podczas udostępniania projektu innym osobom. Informacje o pakietach powinny zostać zapisane przez pip freeze -r requirements.txt.

Lucioric2000
źródło
-1

Jeśli tylko konfigurujesz środowisko programistyczne, użyj pliku pip freeze, caz, który sprawia, że ​​repozytorium git jest czyste.

Następnie, jeśli wykonujesz wdrożenie produkcyjne, sprawdź cały folder Venv. To sprawi, że twoje wdrożenie będzie bardziej powtarzalne, nie będziesz potrzebować tych pakietów libxxx-dev i unikniesz problemów z Internetem.

Istnieją więc dwa repo. Jeden dla twojego głównego kodu źródłowego, który zawiera wymagania.txt. I repozytorium env, które zawiera cały folder venv.

Shuo
źródło