Ich habe eine requirements.txt
Datei, die ich mit Travis-CI verwende. Es scheint albern, die Anforderungen in beiden zu duplizieren, requirements.txt
und setup.py
so hatte ich gehofft, ein install_requires
Dateihandle an das kwarg in zu übergeben setuptools.setup
.
Ist das möglich? Wenn ja, wie soll ich vorgehen?
Hier ist meine requirements.txt
Datei:
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
wird verwendet, um Abhängigkeiten von Paketen zu deklarieren, die für das Funktionieren des Pakets erforderlich sind und vom Entwickler des Pakets verwendet werden, währendrequirements.txt
die Installation von Umgebungen automatisiert wird. Dies ermöglicht die Installation zusätzlicher Software und das Fixieren der Version und wird von Systemadministratoren verwendet, die das Paket bereitstellen Paket. Ihre Rolle und Zielgruppe unterscheiden sich erheblich, daher ist der Versuch, sie wie OP-Wünsche zu kombinieren, imho ein echter Designfehler.[line.strip() for line in open("requirements.txt").readlines()]
?pkg_resources.parse_requirements()
Antworten:
Sie können es umdrehen und die Abhängigkeiten
setup.py
auflisten.
undrequirements.txt
stattdessen ein einzelnes Zeichen - einen Punkt - einfügen.Alternativ ist es auch dann möglich, die
requirements.txt
Datei mit dem folgenden Hack (getestet mitpip 9.0.1
) zu analysieren, wenn dies nicht empfohlen wird (wenn keine externen Anforderungen per URL angegeben werden ):Dies filtert jedoch keine Umgebungsmarkierungen .
In alten Versionen von pip, insbesondere älter als 6.0 , gibt es eine öffentliche API, mit der dies erreicht werden kann. Eine Anforderungsdatei kann Kommentare (
#
) und einige andere Dateien (--requirement
oder-r
) enthalten. Wenn Sie also wirklich a analysieren möchten,requirements.txt
können Sie den Pip-Parser verwenden:quelle
setup(..., dependency_links=[str(req_line.url) for req_line in parse_requirements(<requirements_path>)], ...)
pip
standardmäßig Abhängigkeiten vonsetup.py
in Abwesenheit von analysiert werdenrequirements.txt
, besteht die einfache Antwort , die Tobu unten scharfsinnig notiert, darin, alle Abhängigkeitensetup.py
requirements.txt
aufzulisten und zu entfernen . Reduzieren Sie für Anwendungen, die beides erfordern, einfach die Abhängigkeitslisterequirements.txt
auf das.
Zeichen. Erledigt.Auf den ersten Blick scheint es so,
requirements.txt
alssetup.py
wären es alberne Duplikate, aber es ist wichtig zu verstehen, dass die beabsichtigte Funktion sehr unterschiedlich ist, obwohl die Form ähnlich ist.Das Ziel eines Paketautors bei der Angabe von Abhängigkeiten besteht darin, zu sagen: "Wo immer Sie dieses Paket installieren, sind dies die anderen Pakete, die Sie benötigen, damit dieses Paket funktioniert."
Im Gegensatz dazu hat der Bereitstellungsautor (der zu einem anderen Zeitpunkt dieselbe Person sein kann) einen anderen Job, da er sagt: "Hier ist die Liste der Pakete, die wir zusammengestellt und getestet haben und die ich jetzt installieren muss."
Der Paketautor schreibt für eine Vielzahl von Szenarien, da sie ihre Arbeit dort einsetzen, um sie auf eine Weise zu verwenden, von der sie möglicherweise nichts wissen, und nicht wissen können, welche Pakete neben ihrem Paket installiert werden. Um ein guter Nachbar zu sein und Konflikte mit Abhängigkeitsversionen mit anderen Paketen zu vermeiden, müssen sie eine möglichst große Anzahl von Abhängigkeitsversionen angeben, die möglicherweise funktionieren. Dies ist, was
install_requires
insetup.py
tut.Der Bereitstellungsautor schreibt für ein ganz anderes, sehr spezifisches Ziel: eine einzelne Instanz einer installierten Anwendung oder eines installierten Dienstes, die auf einem bestimmten Computer installiert ist. Um eine Bereitstellung genau zu steuern und sicherzustellen, dass die richtigen Pakete getestet und bereitgestellt werden, muss der Bereitstellungsautor die genaue Version und den Quellspeicherort jedes zu installierenden Pakets angeben, einschließlich der Abhängigkeiten und Abhängigkeiten der Abhängigkeiten. Mit dieser Spezifikation kann eine Bereitstellung wiederholt auf mehrere Computer angewendet oder auf einem Testcomputer getestet werden, und der Bereitstellungsautor kann sicher sein, dass jedes Mal dieselben Pakete bereitgestellt werden. Das macht ein
requirements.txt
.Sie sehen also, dass beide Dinge wie eine große Liste von Paketen und Versionen aussehen, diese beiden Dinge jedoch sehr unterschiedliche Aufgaben haben. Und es ist definitiv einfach, dies zu verwechseln und falsch zu verstehen! Der richtige Weg, darüber nachzudenken,
requirements.txt
ist jedoch eine "Antwort" auf die "Frage", die sich aus den Anforderungen in allen verschiedenensetup.py
Paketdateien ergibt. Anstatt es von Hand zu schreiben, wird es häufig generiert, indem pip angewiesen wird, allesetup.py
Dateien in einer Reihe gewünschter Pakete zu betrachten, eine Reihe von Paketen zu finden, von denen es glaubt, dass sie alle Anforderungen erfüllen, und dann, nachdem sie installiert wurden, "einzufrieren" "diese Liste von Paketen in eine Textdatei (hier kommt derpip freeze
Name her).Also zum Mitnehmen:
setup.py
sollte die lockersten möglichen Abhängigkeitsversionen deklarieren, die noch funktionsfähig sind. Seine Aufgabe ist es zu sagen, womit ein bestimmtes Paket funktionieren kann.requirements.txt
ist ein Bereitstellungsmanifest, das einen gesamten Installationsjob definiert und nicht als an ein Paket gebunden angesehen werden sollte. Seine Aufgabe ist es, eine vollständige Liste aller erforderlichen Pakete zu deklarieren, damit eine Bereitstellung funktioniert.Verweise:
quelle
requirements.txt
zusammen mit der Quelle des Pakets beibehalten würde, das die konkreten / eingefrorenen Anforderungen für die Installation oder den Test enthält. Sicherlichsetup.py
kann sich im Rahmen des Projekts für diesen Zweck verwendet werden? Ich kann nur eine solche Datei für Werkzeuge zur Unterstützung verwendet imagine mit der Verwaltung des Projekts (zB Refactoring, so dass Meldungen etc.).requirements.txt
ist mehr Dokumentation für den Zustand der Welt, der einen bestimmten Build erstellt hat, obwohl er normalerweise nicht im Build-Prozess selbst verwendet wird? Das macht Sinn. Es sieht jedoch so aus, als ob mehrere Systeme auf Duplizierung angewiesen sind: Travis installiert einige (alte) Standardpakete in Ihrer virtuellen Umgebung und sagt, dass sie verwendet werden sollenrequirements.txt
. Wenn ich frage, wie sichergestellt werden kann, dass Abhängigkeiten spätestens verwendet werdensetup.py
, bestehen die Leute darauf, dass ich sie verwenden sollterequirements.txt
.Es kann kein Dateihandle aufnehmen. Das
install_requires
Argument kann nur eine Zeichenfolge oder eine Liste von Zeichenfolgen sein .Sie können Ihre Datei natürlich im Setup-Skript lesen und als Liste von Zeichenfolgen an übergeben
install_requires
.quelle
install_requires
. Es funktioniert jedoch nicht, wenn Sie keine deklarative Syntax verwenden.setup.py
ist ein Programm, das ausgeführt werden soll, keine Datendatei, die analysiert werden soll. Das macht diese Antwort nicht schlimmer.include requirements.txt
in IhremMANIFEST.in
oder Sie werden nicht in der Lage sein , Ihre Bibliothek aus einer Quelldistribution zu installieren.Anforderungsdateien verwenden ein erweitertes Pip-Format, das nur dann nützlich ist, wenn Sie Ihre
setup.py
mit stärkeren Einschränkungen ergänzen müssen , z. B. indem Sie die genauen URLs angeben, von denen einige der Abhängigkeiten stammen müssen, oder die Ausgabe vonpip freeze
, um das gesamte Paketset auf bekanntes Funktionieren einzufrieren Versionen. Wenn Sie die zusätzlichen Einschränkungen nicht benötigen, verwenden Sie nur asetup.py
. Wenn Sie das Gefühl haben, dass Sie wirklich einerequirements.txt
versenden müssen, können Sie daraus eine einzelne Zeile machen:Es ist gültig und bezieht sich genau auf den Inhalt von, der
setup.py
sich im selben Verzeichnis befindet.quelle
pip install -r requirements.txt
) zu installieren, ohne das Paket selbst zu installieren, um zu erläutern, was @ffeast fragt, ob Anforderungen nur in setup.py vorhanden sind ?-e .
sollte ausreichen. Überprüfen Sie diese Seite: caremad.io/posts/2013/07/setup-vs-requirementObwohl dies keine genaue Antwort auf die Frage ist, empfehle ich Donald Stuffts Blog-Post unter https://caremad.io/2013/07/setup-vs-requirement/, um dieses Problem gut zu lösen. Ich habe es mit großem Erfolg eingesetzt.
Kurz gesagt,
requirements.txt
ist keinesetup.py
Alternative, sondern eine Ergänzung zur Bereitstellung. Behalten Sie eine angemessene Abstraktion der Paketabhängigkeiten in beisetup.py
. Legen Sierequirements.txt
mindestens mehrere fest, um bestimmte Versionen von Paketabhängigkeiten für Entwicklung, Test oder Produktion abzurufen.ZB mit Paketen im Repo unter
deps/
:pip führt Pakete aus
setup.py
und installiert die spezifischen Versionen der in deklarierten Abhängigkeiteninstall_requires
. Es gibt keine Duplizität und der Zweck beider Artefakte bleibt erhalten.quelle
pip install my-package
. Wenn Abhängigkeiten für my-package nicht in my-package / setup.py aufgeführt sind, werden sie nicht von installiertpip install my-package
. Ich konnte nicht feststellen, wie ein Paket für andere bereitgestellt werden soll, das Abhängigkeiten enthält, ohne sie explizit in setup.py anzugeben. Würde gerne wissen, ob jemand herausgefunden hat, wie man es trocken hält, während andere es erlauben, my-package + Abhängigkeiten zu installieren, ohne die Anforderungsdatei herunterzuladen und manuell aufzurufenpip install -r my-package/requirements.txt
.requirements.txt
. Das ist der springende Punkt. Die Frage wurde aktualisiert, um die Dinge klarer zu machen. Außerdem wurde der Link zum veralteten Blog-Beitrag aktualisiert.Die Verwendung
parse_requirements
ist problematisch, da die pip-API nicht öffentlich dokumentiert und unterstützt wird. In Pip 1.6 bewegt sich diese Funktion tatsächlich, sodass bestehende Verwendungen davon wahrscheinlich nicht mehr funktionieren.Eine zuverlässigere Möglichkeit, Doppelarbeit zwischen
setup.py
undrequirements.txt
zu vermeiden, besteht darin, Ihre Abhängigkeiten in Ihrer Datei anzugebensetup.py
und diese dann-e .
in Ihrerequirements.txt
Datei einzufügen. Einige Informationen von einem derpip
Entwickler darüber, warum dies ein besserer Weg ist, finden Sie hier: https://caremad.io/blog/setup-vs-requirement/quelle
Die meisten der oben genannten Antworten funktionieren nicht mit der aktuellen Version der Pip-API. Hier ist die richtige * Methode, um dies mit der aktuellen Version von pip zu tun (6.0.8 zum Zeitpunkt des Schreibens, ebenfalls in 7.1.2. Sie können Ihre Version mit pip -V überprüfen).
* Richtig, da es die Art ist, parse_requirements mit dem aktuellen Pip zu verwenden. Es ist wahrscheinlich immer noch nicht der beste Weg, dies zu tun, da pip, wie oben auf den Postern erwähnt, keine API verwaltet.
quelle
Installieren Sie das aktuelle Paket in Travis. Dies vermeidet die Verwendung einer
requirements.txt
Datei. Zum Beispiel:quelle
pip freeze
und diese Datei irgendwo als Artefakt exportieren kann (wie S3 oder so), Sie eine großartige Möglichkeit haben, genau das zu wiederholen, was Sie tun geprüft.from pip.req import parse_requirements
hat bei mir nicht funktioniert und ich denke, es ist für die Leerzeilen in meiner Anforderung.txt, aber diese Funktion funktioniertquelle
Wenn Sie Ihre Benutzer nicht zwingen möchten, pip zu installieren, können Sie das folgende Verhalten emulieren:
quelle
Die folgende Schnittstelle wurde in Pip 10 veraltet:
Also habe ich es einfach auf einfaches Parsen von Text umgestellt:
quelle
pathlib
Variation davon ist.Dieser einfache Ansatz liest die Anforderungsdatei aus
setup.py
. Es ist eine Variation der Antwort von Dmitiry S. . Diese Antwort ist nur mit Python 3.6+ kompatibel.Pro DS ,
requirements.txt
können konkrete Anforderungen mit spezifischen Versionsnummern dokumentieren, währendsetup.py
abstrakte Anforderungen mit loser Version Bereichen dokumentieren.Unten ist ein Auszug von mir
setup.py
.Beachten Sie, dass
distutils.text_file.TextFile
Kommentare entfernt werden. Nach meiner Erfahrung müssen Sie anscheinend keine besonderen Schritte unternehmen, um die Anforderungsdatei zu bündeln.quelle
Hüten Sie sich vor dem
parse_requirements
Verhalten!Bitte beachten Sie, dass dadurch
pip.req.parse_requirements
Unterstriche in Bindestriche umgewandelt werden. Das machte mich ein paar Tage lang wütend, bevor ich es entdeckte. Beispiel zur Demonstration:produziert
quelle
[ir.req.unsafe_name for ir in req_deps if ir.req is not None]
Ich habe dafür eine wiederverwendbare Funktion erstellt. Es analysiert tatsächlich ein ganzes Verzeichnis von Anforderungsdateien und setzt sie auf extras_require.
Neueste immer hier verfügbar: https://gist.github.com/akatrevorjay/293c26fefa24a7b812f5
quelle
pip._internal
. Wenn Sie keine verwendbare externe API bereitstellen, sollten Sie nicht alle brechen die alles verwenden, was Sie zur Verfügung stellen.Eine andere mögliche Lösung ...
und dann zu benutzen ...
quelle
tree
kommen aus?Ich würde so etwas nicht empfehlen. Wie mehrfach erwähnt
install_requires
undrequirements.txt
sollen definitiv nicht die gleiche Liste sein. Aber da es viele irreführende Antworten gibt, die private interne APIs von pip betreffen betreffen, lohnt es sich möglicherweise, nach vernünftigeren Alternativen zu suchen ...Es besteht keine Notwendigkeit für pip eine parsen
requirements.txt
Datei von einem Setuptoolsetup.py
Skript. Das setuptools- Projekt enthält bereits alle erforderlichen Tools in seinem Top-Level- Paketpkg_resources
.Es könnte mehr oder weniger so aussehen:
quelle
pip
Parsing verwenden und nicht . Dieses genaue Problem ist heutzutage behoben, aber ich habe immer noch ein bisschen Angst, es zu verwenden, da beide Implementierungen scheinbar separat entwickelt wurden.pkg_resources
Cross-Posting meiner Antwort von dieser SO-Frage für eine andere einfache, pip-versionssichere Lösung.
Dann geben Sie einfach alle Ihre Anforderungen
requirements.txt
unter Projektstammverzeichnis ein.quelle
Ich war das:
quelle
Ein weiterer
parse_requirements
Hack, der auch Umgebungsmarkierungen analysiertextras_require
:Es sollte sowohl sdist als auch binäre Dists unterstützen.
Wie von anderen angegeben,
parse_requirements
weist es mehrere Mängel auf, sodass Sie dies bei öffentlichen Projekten nicht tun sollten, dies kann jedoch für interne / persönliche Projekte ausreichen.quelle
parse_requirements()
, daher schlägt dies jetzt fehl.Hier ist ein vollständiger Hack (getestet mit
pip 9.0.1
) basierend auf Romains Antwort , derrequirements.txt
ihn gemäß den aktuellen Umgebungsmarkierungen analysiert und filtert :quelle
r.match_markers()
, werten Sie tatsächlich die Marker aus, was für einen SDIST richtig ist. Wenn Sie jedoch eine binäre Dist (z. B. ein Rad) erstellen, listet das Paket nur die Bibliotheken auf, die Ihrer Build-Time-Umgebung entsprechen.wheel environment
(wenn es das ist, was die Person versucht), um Marker dagegen zu bewerten?bdist_wheel
. Marker werden nicht ausgewertet, sondern nur hinzugefügtextras_require
.