Requirements.txt vs setup.py


111

Zacząłem pracować z Pythonem. Dodałem requirements.txti setup.pydo mojego projektu. Ale nadal nie mam pojęcia, jaki jest cel obu plików. Czytałem, że setup.pyjest przeznaczony do rzeczy podlegających redystrybucji i requirements.txtjest przeznaczony do rzeczy, które nie podlegają redystrybucji. Ale nie jestem pewien, czy to prawda.

Jak naprawdę mają być używane te dwa pliki?


1
Czy szukałeś w internecie dokładnego tytułu? Ten artykuł (pierwszy hit podczas wyszukiwania) jest najlepszym, jaki przeczytałem na ten temat.
Chris

2
Ten artykuł może być przydatny: caremad.io/posts/2013/07/setup-vs-requirement (przepraszam, zbyt leniwy, aby wyodrębnić podstawowe elementy w prawidłowej odpowiedzi). Inną rzeczą jest to, że niektóre narzędzia (np. Testowanie) mogą mieć swoje uprzedzenia do jednego lub drugiego - ale nie przejmuj się tym, jeśli dopiero zaczynasz pracę nad Pythonem.
drdaeman

Odpowiedzi:


84

wymagania.txt

Pomaga to skonfigurować środowisko programistyczne. Programy takie jak pipmogą być użyte do zainstalowania wszystkich pakietów wymienionych w pliku za jednym zamachem. Następnie możesz rozpocząć tworzenie skryptu w języku Python. Jest to szczególnie przydatne, jeśli planujesz, aby inne osoby przyczyniły się do rozwoju lub korzystania ze środowisk wirtualnych. Oto jak tego używasz:

pip install -r requirements.txt

setup.py

Pozwala to na tworzenie pakietów, które można redystrybuować. Ten skrypt ma na celu zainstalowanie pakietu w systemie użytkownika końcowego, a nie przygotowanie środowiska programistycznego, jak to pip install -r requirements.txtma miejsce. Zobacz tę odpowiedź, aby uzyskać więcej informacji na temat setup.py.

Zależności projektu są wymienione w obu plikach.


2
W jakich przypadkach miałbym tylko jeden z nich? W którym miałbym oba?
Martin Thoma,

29
Erm ... po prostu piszesz dla zabawy na swojej lokalnej maszynie: Ani jedno, ani drugie. Skrypt jest tworzony na wielu komputerach / vitualenvs, ale nie jest redystrybuowany: wymagania.txt. Skrypt jest tworzony tylko na twoim komputerze, ale powinien być redystrybuowany: setup.py. Skrypt będzie rozpowszechniany i rozwijany w wielu środowiskach: w obu.
AndreasT

Czy możesz dodać to do odpowiedzi?
Martin Thoma

58

Krótka odpowiedź jest taka, że requirements.txtwystarczy wymienić wymagania dotyczące pakietu. setup.pyz drugiej strony bardziej przypomina skrypt instalacyjny. Jeśli nie planujesz instalowania kodu w Pythonie, zwykle potrzebujesz tylko requirements.txt.

Plik setup.pyopisuje, oprócz zależności pakietu, zestaw plików i modułów, które powinny być spakowane (lub skompilowane, w przypadku modułów natywnych (tj. Napisane w C)) oraz metadane, które należy dodać do listy pakietów pythona ( np. nazwa pakietu, wersja pakietu, opis pakietu, autor, ...).

Ponieważ oba pliki zawierają zależności, może to prowadzić do pewnego powielenia. Przeczytaj poniżej, aby uzyskać szczegółowe informacje.

wymagania.txt


Ten plik zawiera listę wymagań dotyczących pakietów Pythona. Jest to zwykły plik tekstowy (opcjonalnie z komentarzami), który zawiera listę zależności pakietów projektu w języku Python (po jednym w każdym wierszu). Tak nie jest opisują sposób, w którym został zainstalowany pakiet python. Zwykle zużywałbyś plik wymagań z rozszerzeniem pip install -r requirements.txt.

Nazwa pliku tekstowego jest dowolna, ale często wynika requirements.txtz konwencji. Podczas eksploracji repozytoriów kodu źródłowego innych pakietów Pythona możesz natknąć się na inne nazwy, takie jak dev-dependencies.txtlub dependencies-dev.txt. Służą one temu samemu celowi, dependencies.txtale generalnie zawierają listę dodatkowych zależności interesujących deweloperów danego pakietu, mianowicie do testowania kodu źródłowego (np. Pytest, pylint itp.) Przed wydaniem. Użytkownicy pakietu na ogół nie potrzebowaliby całego zestawu zależności programisty do uruchomienia pakietu.

Jeśli requirements-X.txtistnieje wiele wariantów, zwykle jeden będzie zawierał listę zależności środowiska wykonawczego, a drugi czas kompilacji lub zależności testowe. Niektóre projekty również kaskadowo tworzą swój plik wymagań, tj. Gdy jeden plik wymagań zawiera inny plik ( np ). Może to zmniejszyć liczbę powtórzeń.

setup.py


To jest skrypt w języku Python, który używa setuptoolsmodułu do zdefiniowania pakietu w języku Python (nazwa, dołączone pliki, metadane pakietu i instalacja). Będzie on, podobnie requirements.txt, wyświetlał również listę zależności wykonawczych pakietu. Setuptools to de facto sposób budowania i instalowania pakietów Pythona, ale ma on swoje wady, które z czasem spowodowały rozwój nowych „menedżerów metapakietów”, takich jak pip. Przykładowe wady setuptools to brak możliwości zainstalowania wielu wersji tego samego pakietu oraz brak polecenia odinstalowania.

Gdy użytkownik Pythona to zrobi pip install ./pkgdir_my_module(lub pip install my-module), pip będzie działał setup.pyw podanym katalogu (lub module). Podobnie każdy moduł, który posiada, setup.pymożna pipzainstalować, np. Uruchamiając pip install .z tego samego folderu.

Czy naprawdę potrzebuję obu?


Krótka odpowiedź brzmi: nie, ale dobrze jest mieć jedno i drugie. Osiągają różne cele, ale oba mogą być używane do tworzenia listy zależności.

Jest jedna sztuczka, którą możesz rozważyć, aby uniknąć powielania listy zależności między requirements.txti setup.py. Jeśli napisałeś już w pełni działającą wersję setup.pydla swojego pakietu, a twoje zależności są w większości zewnętrzne, możesz rozważyć prostą, requirements.txtzawierającą tylko następujące elementy:

 # requirements.txt
 #
 # installs dependencies from ./setup.py, and the package itself,
 # in editable mode
 -e .

 # (the -e above is optional). you could also just install the package
 # normally with just the line below (after uncommenting)
 # .

-eTo specjalna pip installopcja, która instaluje dany pakiet w edycji trybu. Po pip -r requirements.txturuchomieniu na tym pliku pip zainstaluje Twoje zależności za pośrednictwem listy w ./setup.py. Opcja edytowalna umieści łącze symboliczne w katalogu instalacyjnym (zamiast jajka lub zarchiwizowanej kopii). Umożliwia programistom edycję kodu w miejscu z repozytorium bez ponownej instalacji.

Możesz także skorzystać z tego, co nazywa się „dodatkami setuptools”, gdy masz oba pliki w repozytorium pakietów. Możesz zdefiniować opcjonalne pakiety w setup.py w niestandardowej kategorii i zainstalować te pakiety tylko z tej kategorii za pomocą pip:

# setup.py
from setuptools import setup
setup(
   name="FOO"
   ...
   extras_require = {
       'dev': ['pylint'],
       'build': ['requests']
   }
   ...
)

a następnie w pliku wymagań:

# install packages in the [build] category, from setup.py
# (path/to/mypkg is the directory where setup.py is)
-e path/to/mypkg[build]

Spowodowałoby to zachowanie wszystkich list zależności wewnątrz setup.py.

Uwaga : pip i setup.py zwykle uruchamiasz z piaskownicy, takiej jak te utworzone za pomocą programu virtualenv. Pozwoli to uniknąć instalowania pakietów Pythona poza kontekstem środowiska programistycznego projektu.


7
i możesz też mieć po prostu bez .w -eśrodku requirements.txt. Ta metoda po prostu deleguje wszystkie wymagania setup.pyi nie musisz nikogo zmuszać do przejścia w tryb edytowalny. Użytkownicy nadal mogą to robić, pip install -e .jeśli chcą.
stason

1
Ciekawa sztuczka z „-e”. w Requirements.txt, ale czy nie jest to sprzeczne z celem wymagania.txt jako dokładnej specyfikacji systemu? Po co w takim razie jeden?
Ben Ogorek

Możesz mieć dokładne wymagania systemowe wewnątrz setup.py. Mając „.” w Requirements.txt sprawia, że ​​używa pliku setup.py w bieżącym folderze. Używanie -e .również używa setup.py do znalezienia zależności, ale łączy bieżący folder (na miejscu, za pomocą dowiązania symbolicznego) w folderze instalacyjnym pip, zamiast robić kopię - -ezwykle używasz tylko wtedy, gdy tworzysz pakiet. Dzięki temu -ezmiany w plikach pakietów Pythona (* .py) zaczną obowiązywać natychmiast w środowisku pip, zamiast wymuszania ponownej instalacji pakietu po każdej zmianie.
init_js

@init_js jest „bieżącym folderem” w odniesieniu do pliku wymagań lub CWD, z którego wywoływany jest pip? To znaczy, jeśli to zrobisz cd foo && pip install -r ./bar/requirements.txt, to wyszuka setup.py w foo/barlub foo? Jeśli to drugie, czy jest sposób na osiągnięcie tego pierwszego?
Dan M.

pip -r REQnie dba o katalog, w którym znajduje się REQ. Można karmić je z FIFO nawet jeśli chcesz: pip install -r <(echo "mylib1"; echo "mylib2";). Gdzie <(CMD)jest podstawianie poleceń bash, a nie przekierowanie stdin.
init_js

12

W trosce o kompletność, oto jak widzę to pod 3 4 różnymi kątami.

  1. Ich cele projektowe są różne

Oto dokładny opis cytowany z oficjalnej dokumentacji (wyróżnienie moje):

Podczas gdy install_requires (w setup.py) definiuje zależności dla pojedynczego projektu , pliki wymagań są często używane do definiowania wymagań dla pełnego środowiska Pythona .

Podczas gdy wymagania install_requires są minimalne, pliki wymagań często zawierają wyczerpującą listę przypiętych wersji w celu uzyskania powtarzalnych instalacji całego środowiska.

Ale może to nie być łatwe do zrozumienia, więc w następnej sekcji podamy 2 faktyczne przykłady pokazujące, w jaki sposób te dwa podejścia powinny być używane w różny sposób.

  1. Ich rzeczywiste zastosowania są zatem (rzekomo) różne

    • Jeśli twój projekt fooma zostać wydany jako samodzielna biblioteka (co oznacza, że ​​inni prawdopodobnie by to zrobili import foo), wtedy ty (i twoi dalsi użytkownicy) chcielibyście mieć elastyczną deklarację zależności, aby twoja biblioteka nie (i nie może ) bądź „wybredny” co do dokładnej wersji TWOICH zależności. Więc zazwyczaj plik setup.py zawierałby takie linie:

      install_requires=[
          'A>=1,<2',
          'B>=2'
      ]
    • Jeśli chcesz w jakiś sposób „udokumentować” lub „przypiąć” swoje DOKŁADNE bieżące środowisko dla swojej aplikacji bar, co oznacza, że ​​Ty lub Twoi użytkownicy chcielibyście korzystać z aplikacji w bartakiej postaci python bar.py, w jakiej jest, tj. Działającej , można zechcieć zamrozić środowisko, aby zawsze zachowywał się tak samo. W takim przypadku Twój plik wymagań wyglądałby tak:

      A==1.2.3
      B==2.3.4
      # It could even contain some dependencies NOT strickly required by your library
      pylint==3.4.5
  2. W rzeczywistości, którego używam?

    • Jeśli tworzysz aplikację, z barktórej będzie korzystał python bar.py, nawet jeśli jest to „tylko skrypt dla zabawy”, nadal zalecamy korzystanie z pliku Requirements.txt, ponieważ, kto wie, w przyszłym tygodniu (czyli w święta Bożego Narodzenia) otrzymasz nowy komputer w prezencie, więc musisz ponownie skonfigurować tam swoje dokładne środowisko.

    • Jeśli tworzysz bibliotekę, fooktóra będzie używana przez import foo, musisz przygotować plik setup.py. Kropka. Ale nadal możesz wybrać jednocześnie plik Requirements.txt, który może:

      (a) być w A==1.2.3stylu (jak wyjaśniono w punkcie 2 powyżej);

      (b) lub po prostu zawierać magiczny singiel .

      .

      co w przybliżeniu oznaczałoby „zainstaluj wymagania w oparciu o setup.py” bez duplikowania. Osobiście uważam, że to ostatnie podejście w pewnym sensie zaciera linię, pogłębia zamieszanie i tak naprawdę NIE dodaje wartości, niemniej jednak jest to sztuczka wywodząca się z podejścia, o którym wspomniał Donald, opiekun opakowań Pythona w swoim poście na blogu .

  3. Różne dolne granice.

    Nawet jeśli spełniłeś powyższe 3 kryteria i poprawnie zdecydowałeś, że twoja biblioteka hybrid-engineużyje a setup.pydo zadeklarowania swojej zależności engine>=1.2.0, a twoja przykładowa aplikacja reliable-carużyje requirements.txtdo zadeklarowania swojej zależności engine>=1.2.3, nawet jeśli najnowsza wersja enginejest już 1.4.0. Jak widzisz, wybór ich dolnej granicy jest nadal nieco inny. A oto dlaczego.

    • hybrid-enginezależy od engine>=1.2.0tego, ponieważ, hipotetycznie rzecz biorąc, potrzebna zdolność "spalania wewnętrznego" została wprowadzona po raz pierwszy w programie engine 1.2.0, a ta zdolność jest koniecznością hybrid-engine, niezależnie od tego, czy w takiej wersji mogą być jakieś (drobne) błędy i zostały poprawione w kolejnych wersjach 1.2.1 , 1.2.2 i 1.2.3.

    • reliable-carzależy od, engine>=1.2.3ponieważ jest to jak dotąd najwcześniejsza wersja BEZ znanych problemów. Oczywiście, w późniejszych wersjach są nowe możliwości, powiedzmy, wprowadzono „silnik elektryczny” engine 1.3.0i „reaktor jądrowy” engine 1.4.0, ale nie są one konieczne w projekcie reliable-car.


„Twoja biblioteka nie byłaby (i nie może) być„ wybredna ”, jeśli chodzi o dokładną wersję TWOICH zależności”. Czy mógłbyś trochę rozwinąć tę kwestię? Domyślam się, że Twój kod jest zazwyczaj testowany tylko z określonymi wersjami zależności, a takie podejście może być nieco niebezpieczne. Zakładam, że biblioteka powinna działać z wieloma wersjami, ponieważ nie chcesz instalować zbyt wielu wersji zależności? Aby zaoszczędzić miejsce na dysku?
Taro Kiritani

@TaroKiritani Właściwie wymieniłem 2 różne scenariusze obok siebie, przypadek biblioteki i przypadek aplikacji. Być może wcześniej nie pracowałeś w bibliotece? Oczekuje się, że jako biblioteka będzie używana przez kolejne pakiety. Więc jeśli jesteś wybredny, aby przypiąć SWOJĄ zależność A==1.2.3, a następnie, jeśli zdarzy się A==1.2.4, że pakiet podrzędny twojej biblioteki będzie zależał , teraz nie będzie sposobu, aby spełnić oba. Rozwiązaniem minimalizującym ten konflikt jest zdefiniowanie przez bibliotekę zakresu, o którym wiesz, że będzie działać. Zakładając, że wiele zewnętrznych bibliotek jest już zgodnych z semver.org , A>=1,<2zadziała.
RayLuo

Nie zdawałem sobie sprawy, że tylko jedna wersja pakietu może być zainstalowana w jednym środowisku. stackoverflow.com/a/6572017/5686692 Dzięki za wyjaśnienie.
Taro Kiritani

1
@TaroKiritani, tak, w przeciwnym razie w jaki sposób aplikacja wiedzą, która wersja fooma import foodać? Ta nietrafiona, zaakceptowana odpowiedź w tym odnośniku, który podałeś, jest doskonałym przykładem tego, dlaczego opiekun pakietu „nie powinien i nie może być wybredny”. :-) Czy teraz mogę prosić o głos za?
RayLuo

1
Mógłbym również skomentować tę nową myśl, ale ta sekcja komentarzy jest już poza tematem i trudna do naśladowania dla nowych przybyszów. Proponuję zadać nowe pytanie „Czy powinniśmy użyć toksyny czy czegoś w tym rodzaju, aby zagwarantować, że moja biblioteka będzie działała na różnych kombinacjach zależności”, a wtedy ludzie będą mogli
zadzwonić
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.