[Python-de] pip-compile

Christopher Arndt chris at chrisarndt.de
Fr Mär 24 15:20:37 EDT 2017


Hallo Thomas und andere Interessierte,

Am 23.03.2017 um 12:07 schrieb Thomas Güttler:
> Ich verstehe nicht so richtig warum dieser Ablauf von pip-tools[1]
> verwendet wird.

ich fange mal mit einer allgemeinen Antwort auf deine letzte Frage an:

> Warum sollte man mit den pip-tools die req.txt Dateien aktualisieren?

* Es müssen in den Eingabe-Dateien nur idR die direkten Abhängigkeiten
definiert werden.
* Die erzeugten Requirements-Dateien pinnen direkte und indirekte
Abhängigkeiten.
* Beim Erstellen der Requirements wird sichergestellt, dass die
gepinnten Versionen auch verfügbar sind, ...
* ... und dass der geforderte Abhängigkeitsgraph auflösbar ist, ...
* und dies auch bei Requirements-Dateien, die von einander abhängen,
z.B. 'production.txt'->'base.txt' und 'dev.txt'->'base.txt'
* Man kann die geforderten Versionen einzelner Dependencies ändern, ohne
dass das unbeabsichtige Änderungen bei anderen Abhängigkeiten hat.

> Ich sehe das so: in setup.py install_requires sind die ungenauen
> Abhängigkeiten eingetragen (kein Pinning).

> irgendwie ist es eine endlose Quelle von Verwirrungen, dass es in der
> Python Welt zwei Wege für die Definition von
> Abhängigkeiten gibt (setup.py/install_requires und req.txt).

"ungenauen" ist etwas ungenau :) In den "install_requires" werden die
abstrakten Abhängigkeiten festgelegt, die die Software braucht. D.h.
hier dürfen idR keine festen Versionen gepinnt werden (!) sondern
höchstens Mindestversionen und u.U. Maximalversionen der Abhängigkeiten.

Die install_requires werden verwendet, wenn aus der Software ein (TGZ,
Wheel, Egg)-Paket gebaut wird und dieses dann via easy_install oder pip
installiert wird. Hast du nun eine Anwendung X, und diese will Paket A
und B installieren, und Paket A hat in seiner setup.py stehen
'install_requires = ["C==1.0"]' und Paket B hat in seiner setup.py
stehen 'install_requires = ["C==2.0"]' kommmt es zu einem
Versionskonflikt: die Abhängigkeiten deiner Software lassen sich nicht
mehr installieren.

In den Requirements-Dateien dagegen stehen nicht die Abhängigkeiten
deiner Anwendung, sondern eine mögliche Lösung des Abhängigkeitsgraphen.
Diese stellt eine Beschreibung der Python-Umgebung für deine Anwedung
dar (Pythonversion, Rechner-Architektur, und OS jetzt mal außen vor
gelassen). Dieser Stand wird installiert, gegen diesen laufen die Tests
und diesen will man auf dem Produktionssystem gleichermaßen herstellen.
Das heisst, in den Requierements-Dateien will ich die genauen Versionen
aller Abhängigkeiten pinnen, denn nur für diese ist getestet, dass sie
sich alle gemeinsam installieren lassen und nur gegen diese sind die
Ergebnisse der Tests valide.

> Dann läuft das CI und wenn alles ok ist, dann wird eine req.txt per "pip
> freeze" erstellt.
> Dies erstelle req.txt enthält dann das Ergebnis des CI: dieser Stand
> (alles version-pinned) ist erfolgreich getestet worden.

Ja, aber wenn du dann die Version einer Dependency aktualisieren willst,
was machst du dann?

* Trage ich die neue Version einfach in die Requierements-Datei ein, ist
nicht sichergestellt, dass sich die neue Version überhaupt mit den
sonstigen Versionen, die in der Requirementsdate gepinnt sind,
installieren lässt.
* Installiere ich die neue Version einfach mit "pip install -U XYZ",
werden höchstwahrscheinlich weitere Abhängkeiten aktuaisiert und es
findet keine Prüfung statt, ob deren neue Versionen mit meiner Anwendung
kompatibel sind. Wo sollte eine solche Einschränkung dokumentiert werden?
* Installiere ich die neue Version mit "pip install -U --no-deps XYZ",
bekommme ich mit einem "pip freeze" danach einen Stand meiner Umgebung,
der sich u.U. gar nicht mehr mit "pip install -r requirements.txt"
installieren lässt, weil die gepinnten Versionen nicht mehr zum
Abhängigkeitsgraphen passen.

Mit pip-tools erhöhe ich einfach die Mindestversion der Abhängigkeit in
der requirements.in Datei, lasse dann nochmal pip-compile laufen und
habe danach eine valide requirements.txt Datei oder bekomme eben gleich
einen Fehler und weiß, dass die Abhängigkeiten nicht zusammen passen
(und nicht erst, wenn versucht wird, "pip install -r ..." im CI oder gar
erst auf dem Staging/Produktionssystem auszuführen).

Ich hoffe, ich habe die Problematik damit etwas verdeutlichen können.
Hier noch der Link zu einem interessanten Blog-Artikel über einen guten
Workflow für pip-tools:

http://jamescooke.info/a-successful-pip-tools-workflow-for-managing-python-package-requirements.html

Diesen habe ich hier (mit einigen kleinen Anpassungen) umgesetzt:

https://github.com/SpotlightKid/python-package-cookiecutter/blob/master/%7B%7B%20cookiecutter.repo_name%20%7D%7D/requirements/Makefile


Chris



-------------- nächster Teil --------------
Ein Dateianhang mit Binärdaten wurde abgetrennt...
Dateiname   : signature.asc
Dateityp    : application/pgp-signature
Dateigröße  : 993 bytes
Beschreibung: OpenPGP digital signature
URL         : <http://mail.python.org/pipermail/python-de/attachments/20170324/739d9f81/attachment.sig>


Mehr Informationen über die Mailingliste python-de