Mam requirements.txt
plik, którego używam z Travis-CI. Wydaje się głupie powielać wymagania zarówno requirements.txt
a setup.py
, więc miałem nadzieję przekazać uchwyt pliku do install_requires
kwarg w setuptools.setup
.
czy to możliwe? Jeśli tak, to jak mam to zrobić?
Oto mój requirements.txt
plik:
guessit>=0.5.2
tvdb_api>=1.8.2
hachoir-metadata>=1.3.3
hachoir-core>=1.3.3
hachoir-parser>=1.3.4
install_requires
służy do deklarowania zależności od pakietów, które są wymagane do działania pakietu i są używane przez programistę pakietu, natomiastrequirements.txt
służy do automatyzacji instalacji środowisk, co umożliwia instalowanie dodatkowego oprogramowania i przypinanie wersji i jest używany przez sysadmins wdrażających pakiet. Ich rola i grupa docelowa różnią się znacznie, więc próba łączenia ich jak życzenia OP jest prawdziwym błędem projektowym imho.[line.strip() for line in open("requirements.txt").readlines()]
?pkg_resources.parse_requirements()
Odpowiedzi:
Można odwrócić go dookoła i lista w zależności
setup.py
i mieć pojedynczy charakter - kropka.
- wrequirements.txt
zamian.Alternatywnie, nawet jeśli nie jest to zalecane, nadal można przeanalizować
requirements.txt
plik (jeśli nie odwołuje żadnych zewnętrznych wymagań przez adres URL) za pomocą następującego hacka (testowanego zpip 9.0.1
):Nie filtruje to jednak znaczników środowiska .
W starych wersjach pipa, a dokładniej starszych niż 6.0 , istnieje publiczny interfejs API, którego można użyć do osiągnięcia tego. Plik wymagań może zawierać komentarze (
#
) i może zawierać inne pliki (--requirement
lub-r
). Zatem jeśli naprawdę chcesz parsować arequirements.txt
, możesz użyć parsera pip:źródło
setup(..., dependency_links=[str(req_line.url) for req_line in parse_requirements(<requirements_path>)], ...)
pip
domyślnie analizowane są zależnościsetup.py
podczas brakurequirements.txt
, prosta odpowiedź , na którą Tobu zauważył poniżej, polega na wyszczególnieniusetup.py
i usunięciu wszystkich zależnościrequirements.txt
. W przypadku aplikacji wymagających obu, wystarczy zmniejszyć listę zależnościrequirements.txt
do.
postaci. Gotowe.Na pierwszy rzut oka, wydaje się, że
requirements.txt
isetup.py
są głupie duplikaty, ale ważne jest, aby zrozumieć, że podczas gdy forma jest podobna, zamierzona funkcja jest zupełnie inna.Celem autora pakietu, określając zależności, jest powiedzenie „gdziekolwiek instalujesz ten pakiet, są to inne pakiety, których potrzebujesz, aby ten pakiet działał”.
W przeciwieństwie do tego autor wdrażania (którym może być ta sama osoba w innym czasie) ma inne zadanie, mówiąc: „Oto lista pakietów, które zebraliśmy i przetestowaliśmy i które muszę teraz zainstalować”.
Autor pakietu pisze dla wielu różnych scenariuszy, ponieważ udostępniają swoją pracę w taki sposób, że mogą nie wiedzieć, i nie mają możliwości dowiedzenia się, jakie pakiety zostaną zainstalowane wraz z pakietem. Aby być dobrym sąsiadem i uniknąć konfliktów wersji zależności z innymi pakietami, muszą określić możliwie szeroki zakres wersji zależności. To, co
install_requires
sięsetup.py
robi.Autor wdrożenia pisze o bardzo innym, bardzo konkretnym celu: pojedynczej instancji zainstalowanej aplikacji lub usługi zainstalowanej na określonym komputerze. Aby dokładnie kontrolować wdrożenie i upewnić się, że odpowiednie pakiety zostały przetestowane i wdrożone, autor wdrażania musi określić dokładną wersję i lokalizację źródłową każdego pakietu do zainstalowania, w tym zależności i zależności zależności. Dzięki tej specyfikacji wdrożenie może być wielokrotnie stosowane na kilku komputerach lub testowane na maszynie testowej, a autor wdrażania może być pewny, że za każdym razem wdrażane są te same pakiety. To właśnie
requirements.txt
robi.Widać więc, że chociaż oba wyglądają jak duża lista pakietów i wersji, te dwie rzeczy mają bardzo różne zadania. I zdecydowanie łatwo to pomieszać i źle to zrobić! Ale właściwym sposobem myślenia o tym jest
requirements.txt
„odpowiedź” na „pytanie” wynikające z wymagań we wszystkichsetup.py
plikach pakietu. Zamiast pisać ręcznie, często jest generowany przez polecenie pipowi, aby sprawdził wszystkiesetup.py
pliki w zestawie pożądanych pakietów, znalazł zestaw pakietów, które jego zdaniem spełniają wszystkie wymagania, a następnie, po ich zainstalowaniu, „zamroził” msgstr "ta lista pakietów do pliku tekstowego (pip freeze
stąd pochodzi nazwa).Więc na wynos:
setup.py
powinien zadeklarować możliwie najlżejsze wersje zależności, które nadal są wykonalne. Jego zadaniem jest określenie, z czym konkretny pakiet może współpracować.requirements.txt
jest manifestem wdrażania, który definiuje całe zadanie instalacyjne i nie powinien być traktowany jako powiązany z żadnym pakietem. Jego zadaniem jest zadeklarowanie wyczerpującej listy wszystkich niezbędnych pakietów do wdrożenia.Bibliografia:
źródło
requirements.txt
wraz ze źródłem pakietu, który zawiera konkretne / zamrożone wymagania dotyczące instalacji lub testowania. Czy na pewnosetup.py
można w tym celu wykorzystać w samym projekcie? Mogę sobie tylko wyobrazić użycie takiego pliku dla narzędzi używanych do wspierania zarządzania projektem (np. Refaktoryzacja, tworzenie wydań itp.).requirements.txt
jest więcej dokumentacji dotyczącej stanu świata, który wyprodukował daną kompilację, nawet jeśli zwykle nie jest używana w samym procesie kompilacji? To ma sens. Wygląda jednak na to, że kilka systemów polega na duplikacji: Travis instaluje domyślne (stare) pakiety w twoim virtualenv i mówi, aby użyćrequirements.txt
. Jeśli zapytam, jak zapewnić, by zależności były w użyciusetup.py
, ludzie nalegają, żebym ich użyłrequirements.txt
.Nie może obsłużyć pliku.
install_requires
Argument może być tylko ciągiem lub listą ciągów .Możesz oczywiście odczytać plik w skrypcie instalacyjnym i przekazać go jako listę ciągów do
install_requires
.źródło
install_requires
. Jednak to nie działa, jeśli nie używasz deklaratywnej składni.setup.py
to program, który powinien zostać uruchomiony, a nie plik danych, który należy przeanalizować. To nie pogarsza tej odpowiedzi.include requirements.txt
goMANIFEST.in
do swojej biblioteki lub nie będzie można zainstalować biblioteki z dystrybucji źródłowej.Pliki wymagań używają rozszerzonego formatu pip, który jest użyteczny tylko wtedy, gdy potrzebujesz uzupełnić swoje
setup.py
silniejsze ograniczenia, na przykład określając dokładne adresy URL, z których niektóre zależności muszą pochodzić, lub dane wyjściowe,pip freeze
aby zamrozić cały zestaw pakietów do znanego działania wersje. Jeśli nie potrzebujesz dodatkowych ograniczeń, użyj tylkosetup.py
. Jeśli czujesz, że naprawdę potrzebujesz wysyłkirequirements.txt
, możesz utworzyć jedną linię:Będzie ważny i będzie odnosił się dokładnie do zawartości tego,
setup.py
który znajduje się w tym samym katalogu.źródło
pip install -r requirements.txt
) bez instalowania samego pakietu?-e .
powinno wystarczyć. Sprawdź tę stronę: caremad.io/posts/2013/07/setup-vs-requirementChociaż nie jest to dokładna odpowiedź na pytanie, polecam post na blogu Donalda Stuffta pod adresem https://caremad.io/2013/07/setup-vs-requirement/, aby dobrze zająć się tym problemem. Użyłem go do wielkiego sukcesu.
Krótko mówiąc,
requirements.txt
nie jestsetup.py
alternatywą, ale uzupełnieniem wdrożenia. Zachowaj odpowiednią abstrakcję zależności pakietów wsetup.py
. Ustawrequirements.txt
lub więcej, aby pobrać określone wersje zależności pakietów do programowania, testowania lub produkcji.Np. Z pakietami zawartymi w repozytorium pod
deps/
:pip wykonuje pakiety
setup.py
i instaluje określone wersje zależności zadeklarowane winstall_requires
. Nie ma duplikatu, a cel obu artefaktów zostaje zachowany.źródło
pip install my-package
. Jeśli zależności dla mojego pakietu nie ma na liście w moim pakiecie / setup.py, nie są one instalowane przezpip install my-package
. Nie udało mi się ustalić, w jaki sposób dostarczyć pakiet dla innych, który zawiera zależności, bez wyraźnego podawania ich w pliku setup.py. Chciałbym wiedzieć, czy ktoś wymyślił, jak zachować SUCHOŚĆ, pozwalając innym na instalowanie zależności mojego pakietu + bez pobierania pliku wymagań i ręcznego wywoływaniapip install -r my-package/requirements.txt
.requirements.txt
. To o to chodzi. Zaktualizowałem pytanie, aby wszystko było bardziej jasne. Zaktualizowany również przestarzały link do posta na blogu.Używanie
parse_requirements
jest problematyczne, ponieważ API pip nie jest publicznie udokumentowane i obsługiwane. W pipie 1.6 ta funkcja faktycznie się porusza, więc istniejące jej zastosowania prawdopodobnie się zepsują.Bardziej niezawodnym sposobem na wyeliminowanie powielania między
setup.py
irequirements.txt
jest określenie zależności w pliku,setup.py
a następnie umieszczenie go-e .
wrequirements.txt
pliku. Niektóre informacje od jednego zpip
programistów o tym, dlaczego jest to lepszy sposób, są dostępne tutaj: https://caremad.io/blog/setup-vs-requirement/źródło
Większość pozostałych odpowiedzi powyżej nie działa z bieżącą wersją API pipa. Oto poprawny * sposób na zrobienie tego z bieżącą wersją pip (6.0.8 w momencie pisania, działał również w 7.1.2. Możesz sprawdzić swoją wersję za pomocą pip -V).
* Prawidłowo, ponieważ jest to sposób na użycie parse_requirements z bieżącym pipem. Prawdopodobnie nie jest to najlepszy sposób, aby to zrobić, ponieważ, jak wspomniano powyżej, pip naprawdę nie utrzymuje interfejsu API.
źródło
Zainstaluj bieżący pakiet w Travis. Pozwala to uniknąć użycia
requirements.txt
pliku. Na przykład:źródło
pip freeze
pliku wymagań.txt i wyeksportowania go gdzieś jako artefaktu (takiego jak S3 lub coś takiego), to byłbyś świetnym sposobem na wielokrotne instalowanie dokładnie tego, co przetestowany.from pip.req import parse_requirements
nie działało dla mnie i myślę, że dotyczy to pustych wierszy w pliku wymagań.txt, ale ta funkcja działaźródło
Jeśli nie chcesz zmuszać użytkowników do instalowania pip, możesz naśladować jego zachowanie za pomocą:
źródło
Następujący interfejs stał się przestarzały w pip 10:
Więc zmieniłem to na zwykłą analizę tekstu:
źródło
pathlib
odmianą .To proste podejście odczytuje plik wymagań z
setup.py
. Jest to odmiana Odpowiedź Dmitiry S. . Ta odpowiedź jest kompatybilna tylko z Python 3.6+.Za DS ,
requirements.txt
może udokumentować konkretne wymagania z numerami konkretnej wersji, asetup.py
może udokumentować abstrakcyjne wymagania z luźnych zakresów wersji.Poniżej znajduje się fragment mojego
setup.py
.Pamiętaj, że
distutils.text_file.TextFile
usunie komentarze. Z mojego doświadczenia wynika, że najwyraźniej nie musisz podejmować żadnych specjalnych kroków w celu dołączenia pliku wymagań.źródło
UWAŻAJ NA
parse_requirements
ZACHOWANIE!Pamiętaj, że
pip.req.parse_requirements
zmieni podkreślenia na myślniki. Rozwścieczyło mnie to przez kilka dni, zanim to odkryłem. Przykład demonstrujący:produkuje
źródło
[ir.req.unsafe_name for ir in req_deps if ir.req is not None]
Stworzyłem do tego funkcję wielokrotnego użytku. W rzeczywistości analizuje cały katalog plików wymagań i ustawia je na dodatkowe wymagania.
Najnowsze zawsze dostępne tutaj: https://gist.github.com/akatrevorjay/293c26fefa24a7b812f5
źródło
pip._internal
... Jeśli nie zapewnisz użytecznego zewnętrznego interfejsu API, nie powinieneś łamać tych wszystkich które wykorzystują wszystko, co zapewniasz.Inne możliwe rozwiązanie ...
a następnie użyć ...
źródło
tree
pochodzi?Nie poleciłbym robić czegoś takiego. Jak wspomniano wiele razy
install_requires
irequirements.txt
zdecydowanie nie powinna to być ta sama lista. Ale ponieważ istnieje wiele mylących odpowiedzi obejmujących prywatne wewnętrzne interfejsy API pip , warto spojrzeć na rozsądniejsze alternatywy ...Pip nie musi analizować
requirements.txt
pliku ze skryptu setuptoolssetup.py
. Projekt setuptools zawiera już wszystkie niezbędne narzędzia w pakiecie najwyższego poziomupkg_resources
.Może mniej więcej wyglądać tak:
źródło
pip
analizowania składni, a niepkg_resources
przed rokiem 2015, są błędy, takie jak github.com/pypa/setuptools/issues/470 . Ta dokładna jest obecnie naprawiona, ale nadal boję się jej użyć, ponieważ obie implementacje wydają się być opracowywane osobno.Cross wysyłając moją odpowiedź z tego pytania SO, dla innego prostego rozwiązania w wersji pip.
Następnie po prostu wprowadź wszystkie swoje wymagania w
requirements.txt
katalogu głównym projektu.źródło
Ja to zrobiłem:
źródło
Kolejny
parse_requirements
hack, który analizuje również znaczniki środowiska wextras_require
:Powinien obsługiwać zarówno sdist, jak i binarne dists.
Jak twierdzą inni,
parse_requirements
ma kilka niedociągnięć, więc nie należy tego robić w projektach publicznych, ale może wystarczyć w przypadku projektów wewnętrznych / osobistych.źródło
parse_requirements()
, więc to się nie udaje.Oto kompletny hack (przetestowany z
pip 9.0.1
) oparty na odpowiedzi Romaina, który analizujerequirements.txt
i filtruje go zgodnie z obecnymi znacznikami środowiska :źródło
r.match_markers()
, faktycznie oceniasz znaczniki, co jest słuszne dla sdist. Jednakże, jeśli budujesz binarkę binarną (np. Koło), pakiet wyświetli tylko te biblioteki, które pasują do twojego środowiska kompilacji.wheel environment
(jeśli to jest rzecz, którą człowiek próbuje zrobić), aby ocenić markery przeciwko niemu?bdist_wheel
. Nie ocenia markerów, tylko je dodajeextras_require
.