Pipenv: Vorschlag: `pipenv`-Muster und Antimuster für das Python-Bibliotheksprojekt

Erstellt am 5. Apr. 2018  ·  74Kommentare  ·  Quelle: pypa/pipenv

Hacken von maya Ich habe einige Lektionen gelernt, die zu meinem folgenden Vorschlag der empfohlenen Verwendung von pipenv in Python-Bibliotheken führten. Ich erwarte, dass andere den Vorschlag überprüfen, und wenn wir eine Einigung erzielen, könnte der (aktualisierte) Text in pipenv Dokumenten enden.

pipenv Muster und Antimuster für das Python-Bibliotheksprojekt

BEARBEITEN
Folgendes gilt am besten für allgemeine (meist Open Source) Python-Bibliotheken, die auf verschiedenen Python-Versionen und Betriebssystemen laufen sollen. Bibliotheken, die in einer strikten Enterprise-Umgebung entwickelt wurden, können unterschiedlich sein (achten Sie auf jeden Fall darauf, alle Abschnitte zu Problemen zu lesen).

ENDE DER BEARBEITUNG

TL;DR : Das Hinzufügen von pipenv Dateien zum Python-Bibliotheksprojekt führt wahrscheinlich zu zusätzlicher Komplexität und kann einige Fehler verbergen, während der Bibliothekssicherheit nichts hinzugefügt wird. Halten Sie aus diesem Grund

Sie können die volle Leistung von pipenv unabhängig davon, welche Dateien sich in .gitignore .

Python-Bibliothek im Vergleich zu Python-Anwendung

Mit Python- Bibliothek meine ich ein Projekt mit normalerweise setup.py , das auf die Verteilung und Verwendung auf verschiedenen Plattformen ausgerichtet ist, die sich in Python-Version und / oder Betriebssystem unterscheiden.

Beispiele sind maya , requests , flask usw.

Auf der anderen Seite (keine Python-Bibliothek) gibt es Anwendungen, die auf bestimmte Python-Interpreter und Betriebssysteme ausgerichtet sind und oft in einer streng konsistenten Umgebung bereitgestellt werden.

pipfile beschreibt diese Unterschiede sehr gut in Pipfile vs setup.py .

Was ist pipenv (Bereitstellungstool)

Ich stimme der Aussage voll und ganz zu, dass pipenv ein Bereitstellungstool ist, da es Folgendes ermöglicht:

  • definieren strenge Anforderungen ( Pipfile.lock ) für die Bereitstellung der virtuellen Umgebung
  • Wenden Sie diese strengen Anforderungen reproduzierbar auf verschiedenen Maschinen an

Es hilft, wenn man eine Anwendung bereitstellen oder in einer Python-Umgebung entwickeln muss, die über mehrere Entwickler hinweg sehr konsistent ist.

pipenv Paketierungstool aufzurufen ist irreführend, wenn man davon ausgeht, dass es Python-Bibliotheken erstellt oder tief in deren Erstellung beteiligt ist. Ja, pipenv kann viel helfen (bei der lokalen Entwicklung von Bibliotheken), kann aber möglicherweise schaden (oft bei CI-Tests, wenn es ohne tiefere Überlegung verwendet wird).

"Sicherheitsgründe" im falschen Kontext anwenden

TL;DR : pipenv bietet eine sichere Umgebung, indem genehmigte konkrete Abhängigkeiten angewendet werden, die in der Datei Pipfile.lock , und die Python-Bibliothek darf nur abstrakte Abhängigkeiten definieren (also kann Pipfile.lock nicht bereitstellen).

pipenv glänzt in Bereitstellungsszenarien, die diesen Schritten folgen:

  • abstrakte Abhängigkeiten definieren (über Pipfile )
  • daraus konkrete Abhängigkeiten generieren, die Pipfile.lock
  • Erstellen Sie eine (virtuelle) Python-Umgebung, die diese konkreten Abhängigkeiten widerspiegelt
  • Führen Sie Tests durch, um sicherzustellen, dass die gegebene Umgebung wie erwartet funktioniert und sicher ist
  • die getesteten "goldenen" Pipfile.lock als Definition einer genehmigten Python-Umgebung freigeben
  • andere können pipenv sync , um "das goldene" Pipfile.lock anderswo anzuwenden, um eine identische Python-Umgebung zu erhalten.

Mit der Entwicklung von Python-Bibliotheken kann man eine solche Sicherheit nicht erreichen, da Bibliotheken keine konkreten Abhängigkeiten definieren müssen . Das Brechen dieser Regel (also der Versuch, konkrete Abhängigkeiten durch die Python-Bibliothek zu deklarieren) führt zu Problemen wie:

  • Probleme, eine zufriedenstellende Version von Shared Libraries zu finden (jedes strikte Paket definiert die genaue Version der Shared Library und es ist sehr wahrscheinlich, dass sich die Versionen unterscheiden und das Auffinden einer allgemein akzeptablen Version verhindern)
  • konkrete Abhängigkeiten können von der Python-Version, dem Betriebssystem oder anderen Umgebungsmarkierungen abhängen, und der Versuch, das Paket in einem anderen Kontext zu installieren, kann leicht einige der in den ursprünglichen abstrakten Abhängigkeiten definierten Regeln nicht erfüllen.

Problem: Verstecken defekter setup.py definierter Abhängigkeiten

setup.py soll alle abstrakten Abhängigkeiten über install_requires .

Wenn Pipfile diese Abhängigkeiten definiert, können Probleme wie:

  • fehlende Abhängigkeit in install_requires
  • Pipfile definiert bestimmte Regeln (Versionsbereiche etc.) für eine Abhängigkeit und install_requires nicht.

Um dies zu verhindern, befolgen Sie diese Regeln:

  • bibliotheksdefinierte Abhängigkeiten dürfen nicht in Pipfile
  • der Abschnitt [packages] in Pipfile soll entweder leer sein oder nur eine einzelne Abhängigkeit von der Bibliothek selbst definieren.

Problem: Pipfile.lock im Repository

Es ist falsch, Pipfile.lock (normalerweise aus "Sicherheitsgründen") im Bibliotheksrepository zu behalten, weil:

  • beschriebene Abhängigkeiten sind wahrscheinlich für verschiedene Python-Versionen oder in einem anderen Betriebssystem ungültig
  • Entwickler sind nicht nur gezwungen, die Datei zu aktualisieren, wenn sie Abhängigkeiten hinzufügen/entfernen, sondern auch, wenn andere Bibliotheken aktualisiert werden und innerhalb der Bibliothek verwendet werden können.

Um dies zu verhindern, sollte man:

  • entferne Pipfile.lock aus dem Repository und füge es zu .gitignore

Problem: Konkurrieren mit tox (versteckt usedevelop )

Wenn tox.ini in seinem Abschnitt commands Einträge enthält wie:

  • pipenv install
  • pipenv install --dev
  • pipenv lock

es ist oft ein Problem, denn:

  • pipenv install soll nur die Bibliothek selbst installieren und tox tut dies (standardmäßig) auch. Abgesehen von Duplizität verhindert es auch usedevelop=True und usedevelop=False in tox.ini weil Pipenv es nur in einer Variante ausdrücken kann (und tox.ini erlaubt Unterschiede in verschiedenen Umgebungen).

Um dies zu verhindern, sollte man:

Problem: Unterbrechen von Builds, wenn pipenv fehlschlägt

pipenv befindet sich in der Entwicklungsphase und die Dinge gehen irgendwann kaputt. Wenn ein solches Problem Ihren CI-Build unterbricht, gibt es einen Fehler, der verhindert werden könnte, indem Sie pipenv und traditionelle Tools (die oft etwas ausgereifter sind) verwenden.

Um dies zu verhindern, sollte man:

  • Überlegen Sie zweimal, bevor Sie pipenv in ein CI-Build-Skript, tox.ini oder ähnliches einfügen. Wissen Sie, welchen Wert Sie durch das Hinzufügen erhalten? Könnte die Arbeit mit vorhandenen Werkzeugen erledigt werden?
  • nicht hinzufügen "nur aus Sicherheitsgründen" oder weil "jeder das tut".

Zusammenfassung

Die wichtigsten Fragen zur Rolle von pipenv bei der Entwicklung der Python-Bibliothek sind:

  • Welchen Wert bringt pipenv wirklich? A: Virtualenv-Verwaltungstool.
  • Was ist ein relevanter Anwendungsfall für pipenv ? A: Virtualenv verwalten.
  • Soll es im Bibliotheksrepository erscheinen? A: NEIN.

Einige weitere Details und Tricks folgen.

pipenv fügt Ihrem Paket keine Sicherheit hinzu

Schieben Sie es nicht ins Projekt, nur weil es jeder macht oder weil Sie zusätzliche Sicherheit erwarten. Es wird dich enttäuschen.

Die Absicherung durch konkrete (und genehmigte) Abhängigkeiten erfolgt in einer späteren Phase des Antrags auf Nutzung Ihrer Bibliothek.

Halten Sie Pipfile , Pipfile.lock und .env Dateien aus dem Repository fern

Legen Sie die Dateien in .gitignore .

Pipfile sich leicht nachbauen, wie unten gezeigt, da die meisten oder alle Anforderungen bereits in Ihrem setup.py . Und die Datei .env enthält wahrscheinlich private Informationen, die nicht weitergegeben werden sollen.

Wenn Sie diese Dateien aus dem Repository heraushalten, werden alle Probleme vermieden, die bei CI-Builds auftreten können, wenn pipenv in Situationen verwendet wird, die nicht angemessen sind.

pipenv als private Toolbox des Entwicklers

pipenv kann die Arbeit des Entwicklers als Virtualenv-Verwaltungstool vereinfachen.

Der Trick besteht darin, zu lernen, wie Sie Ihre (privaten) pipenv bezogenen Dateien schnell neu erstellen können, zB:

$ cd <project_repository>
$ # your library will bring the dependencies (via install_requires in setup.py)
$ pipenv install -e .   
$ # add more dev tools you preffer 
$ pipenv install --dev ipython pdbpp
$ # start hacking
$ pipenv shell
...

Verwenden Sie die Datei .env , wenn Sie eine bequeme Methode zum Einrichten von Umgebungsvariablen benötigen.

Denken Sie daran: Halten Sie die Nutzung von pipenv aus Ihren CI-Builds heraus und Ihr Leben wird einfacher.

Trick: Verwenden Sie die Fähigkeit setup.py , um Abhängigkeiten von Extras zu deklarieren

Verwenden Sie in Ihrem setup.py den Abschnitt extras_requires :

from setuptools import setup

setup(
    name='mypackage',
    ....,
    install_requires=["jinja2", "simplejson"],
    extras_require={
        'tests': ['pytest', 'pyyaml'],
        'pg': ['psycopg2'],
    },
    ....
)

Um alle für tests deklarierten Abhängigkeiten zu installieren:

$ pipenv install -e .[tests]

Beachten Sie, dass es immer die install_requires Abhängigkeiten enthält.

Diese Methode erlaubt es nicht, Abhängigkeiten in Default- und Dev-Abschnitte aufzuteilen, aber dies sollte in erwarteten Szenarien kein wirkliches Problem darstellen.

Discussion Type

Hilfreichster Kommentar

@ Moritz90 Mehrere Mailinglisten von Python wären gute Orte, um diese Diskussion zu führen.

pypa-dev ist am besten umgebende Ökosystem. Ich würde wahrscheinlich hier anfangen, wenn ich eine ähnliche Diskussion posten würde.

python-ideas ist ein Ort, um Ideen zu diskutieren, und hat eine ziemlich hohe Sichtbarkeit für die gesamte Python-Community. Es wäre auch ein guter Ausgangspunkt, wenn Sie dies auf die PEP-Ebene bringen möchten (ich denke, Sie würden es irgendwann tun).

Alle 74 Kommentare

Das ist sehr beeindruckend, vielen Dank fürs Kompilieren. Werde auf jeden Fall in Kürze genauer rezensieren

/cc @uranusjr @jtratner @ncoghlan

Einige Hinweise auf maya Probleme:

  • kennethreitz/maya#138 (EntfernePipfile.lock aus dem Repository)
  • kennethreitz/maya#139 (Pipenv run in tox.ini überspringen ...)
  • kennethreitz/maya#145 (fix pendulum>=1.0 in setup.py: Version war in Pipfile aber fehlte in setup.py)
  • kennethreitz/maya#143 (PR zeigt, wie das pipenv Problem den ganzen Travis-Lauf brach)
  • kennethreitz/maya#144 (PR Refactor pipenv-Nutzung gemäß halboffizieller Best Practices)

Ich liebe das auch. Vielleicht sollten wir dies der Dokumentation von Pipenv oder sogar dem Python Packaging User Guide hinzufügen.

Die Folge der obigen Ratschläge scheint zu sein, "auf deterministische/reproduzierbare CI-Builds zu verzichten", was mir als sehr großes Anti-Muster erscheint.

Was schlagen Sie als Alternative vor, die noch Determinismus zulassen würde?

@tsiq-oliverc Deterministische Builds haben im Moment ihren Platz, eine Anwendung soll gebaut werden.

Stellen Sie sich den folgenden Versuch vor, wirklich deterministische Builds der Python-Bibliothek durchzuführen:

  • Builds müssen auf Pipfile.lock basieren
  • jeder Ausführungskontext (Kombination jeder Python- und Betriebssystemvariante) kann unterschiedliche Pipfile.lock die sich aus den abstrakten Bibliotheksabhängigkeiten ergeben, die in Pipfile
  • Das Repository müsste separate Pipfile.lock Instanzen bereitstellen, die im Repository definiert sind. Beachten Sie, dass das automatische Erstellen von Pipfile.lock während des CI-Builds keinen Determinismus hinzufügt

Das ist ein großer zusätzlicher Aufwand. Und was Sie bekommen, ist eine Bibliothek, die in einem anderen Kontext installiert wird (zB eine Woche später wird die Standardinstallation aktualisierte Abhängigkeiten oder zwei aufnehmen) und die nichts davon bekommt, dass Sie Pipfile.lock , was ist im Moment obsolet.

Der Konflikt besteht darin, dass die Bibliothek niemals strenge Abhängigkeiten im Inneren definieren darf.

Wenn Sie denken, gibt es eine andere Alternative, um deterministische Builds für die Python-Bibliothek zu erhalten - beschreiben Sie sie.

@vlcinsky - Wenn ein Verbraucher Ihrer Bibliothek verschiedene Versionen von Abhängigkeiten usw. verwendet, liegt dies außerhalb Ihrer Kontrolle. Ich stimme also zu, dass es für einen Bibliotheksverwalter keinen praktikablen Weg gibt, dies zu verwalten.

Aber das Ziel ist hier vermutlich ein viel kleinerer Spielraum. Insbesondere würde ich die Ziele für einen Bibliotheksverwalter wie folgt sehen (was ungefähr Äquivalenzen sind):

  1. Wenn Sie Ihr CI zweimal ausführen, erhalten Sie garantiert das gleiche Ergebnis (trotz Netzwerkproblemen!).
  2. Sie können das Verhalten, das Sie auf CI beobachten, lokal nachbilden (und damit debuggen), auch wenn dies bedeutet, dass Docker/etc. örtlich.
  3. Sie können Ihren Konsumenten getrost sagen "Meine Bibliothek verhält sich wie erwartet mit den Abhängigkeitsversionen X, Y, Z".

Wenn eines dieser drei Dinge nicht zutrifft, erscheint es mir im Gegensatz zur Qualitätskontrolle.

Also ja, ich würde sagen, wenn Sie Ihrem Verbraucher garantieren, die Python-Varianten A, B und C zu unterstützen, und sie sich so unterschiedlich verhalten, dass eine Sperrdatei (usw.) sie nicht schneidet, dann sollten Sie drei Sperrdateien (oder wie auch immer).

Ich habe Pipenv jedoch nicht genug verwendet, um zu wissen, wie einfach das in der Praxis wäre.

Ich überlege derzeit, Pipfile s zu einigen Bibliotheksprojekten für das CI-System hinzuzufügen.

Das Dependency Locking (+Hashing) benötige ich unbedingt, um unternehmensweite Sicherheitsrichtlinien einzuhalten und muss derzeit nicht mit verschiedenen Python-Versionen testen, da nur eine offiziell unterstützt wird. Und dass pipenv das Einrichten einer lokalen Entwicklungsumgebung inklusive virtualenv vereinfacht, ist ein netter Nebeneffekt.

Und was Sie bekommen, ist eine Bibliothek, die in einem anderen Kontext installiert wird (zB eine Woche später wird die Standardinstallation aktualisierte Abhängigkeiten aufnehmen oder zwei) und die nichts davon bekommt, dass Sie Pipfile.lock , was ist im Moment obsolet.

Dies ist nicht allgemein wahr. In der Welt der Unternehmenssoftware gibt es immer noch sehr spezielle Umgebungen, die offiziell unterstützt werden, und ein Sicherheitsproblem in einer Abhängigkeit führt dazu, dass Ihr Produkt aktualisiert wird, anstatt dass der Kunde die Abhängigkeit selbst aktualisiert.

(Ja, ich rede hier von einer Bibliothek, nicht von einer Anwendung...)

@ Moritz90 Ihr Szenario ist für die Python-Bibliothek in einer Unternehmensumgebung und dort kann pipenv helfen, da es sich um eine viel deterministischere Umgebung handelt.

Meine Beschreibung zielt auf allgemeine Python-Bibliotheken wie flask , request , maya usw. ab, bei denen der Kontext viel variabler ist. Als ich versuchte, ein paar Dinge in maya zu beheben, wurde ich frustriert, als ich lernte, dass die Verwendung von pipenv in vielen Fällen echte Probleme mit sich brachte (normalerweise versteckte Probleme, die normalerweise erkannt würden), während nicht viel oder zusätzliches bereitgestellt wurde Wert.

Es ist eine gute Sache, deterministische Builds zu erhalten, aber es verursacht Kosten. Und wenn es falsch gemacht wird, können Sie für ein Ergebnis mit geringerer Qualität extra bezahlen - und das wollte ich verhindern.

Ich würde argumentieren, dass dies einer der Fälle ist, in denen die Builds nicht absolut deterministisch sein sollen. Wenn Sie Ihre Abhängigkeiten nicht mit == anheften, verpflichten Sie sich, standardmäßig mehrere Versionen zu unterstützen, und sollten die Bibliothek so gestalten. Ein Abhängigkeits-Upgrade, das den Build auf CI zerstört, ist eigentlich eine gute Sache, da es einen Fehler in der Bibliothek aufdeckt. Völlig deterministische Abhängigkeiten (wie von Pipenv verwaltet) würden dies maskieren. Es wäre immer noch von Vorteil, deterministisch sein zu können, wenn Sie es wollen, das ist im Allgemeinen nicht das Beste.

@uranusjr - Klar. Ich stimme zu, dass, wenn der Wunsch "nicht deterministische Builds" ist, der Rat oben durchaus sinnvoll sein kann. Tatsächlich ist es fast eine logische Äquivalenz und könnte viel prägnanter formuliert werden: "Wenn Sie keine deterministischen Builds möchten, verwenden Sie kein Tool ( pipenv ), dessen Zweck es ist, deterministische Builds zu gewährleisten." .

Aber das ist im Allgemeinen sicherlich kein wünschenswertes Ziel.

@tsiq-oliverc schöne Scope-Definition - sie unterstützt fokussierte Diskussionen. Ich möchte eine weitere Anforderung hinzufügen: Der CI-Determinismus soll mögliche Probleme innerhalb der getesteten Bibliothek nicht verbergen.

Wenn wir Pipenv.lock , darauf basierend virtualenv erstellen und den CI-Test der Bibliothek ausführen, haben wir einen Teil der Funktionalität der Bibliothek ausgeführt - die Installation der richtigen Abhängigkeiten. Wenn die Bibliothek in dieser Hinsicht irgendwie kaputt ist, würde eine vorinstallierte Umgebung dieses Problem verbergen.

Mir scheint es wichtiger, Probleme innerhalb einer Bibliothek zu erkennen, als CI auf deterministische Weise auszuführen. Wenn es eine Möglichkeit gibt, beides zu tun (zB den Test hinter dem privaten Pypi-Index ausführen, der auch den Determinismus unterstützen könnte), habe ich kein Problem, aber wenn es einen Konflikt gibt, habe ich meine Prioritäten.

Verstehen Sie mich nicht falsch: Es besteht kein Wunsch, nicht-deterministische Builds auszuführen. Mein Wunsch ist es, CI-Builds auszuführen, die so viele Probleme wie möglich erkennen.

@vlcinsky Klar, ich wollte nur meine Erfahrungen teilen, um sicherzustellen, dass die aktualisierte Dokumentation dies auch widerspiegelt. Die aktuelle Dokumentation leistet hervorragende Arbeit, um die Kompromisse zu erklären:

Definieren Sie für Bibliotheken abstrakte Abhängigkeiten über install_requires in setup.py. […]
Definieren Sie für Anwendungen Abhängigkeiten und wo sie in der Pipfile abgerufen werden können, und verwenden Sie diese Datei, um den Satz konkreter Abhängigkeiten in Pipfile.lock zu aktualisieren. […]
Natürlich sind Pipfile und pipenv für Bibliotheksentwickler weiterhin nützlich, da sie zum Definieren einer Entwicklungs- oder Testumgebung verwendet werden können.
Und natürlich gibt es Projekte, bei denen die Unterscheidung zwischen Bibliothek und Anwendung nicht so klar ist.

(Der in meinem Fall zutreffende Teil ist hervorgehoben.)

Ich möchte nur sicherstellen, dass es so bleibt. Ich denke, Ihr ursprünglicher Beitrag enthält zu viele Pauschalaussagen ohne Haftungsausschluss, dass Sie von einem Open-Source-Projekt sprechen, das auf PyPI veröffentlicht wird.

@ Moritz90 Ich stimme

@ Moritz90 Ich habe eine einleitende Anmerkung hinzugefügt, die Ihren Kommentar widerspiegelt.

@vlcinsky - Das macht Sinn. Ich verstehe , dass Sie nicht explizit wollen nicht deterministisch bauen, aber ich denke , dass es unvermeidlich ist äquivalent zu dem, was Sie wollen zu tun (dh zu fangen Probleme , wenn Ihre Upstream - Abhängigkeiten Update).

Was ist der beste Weg, um diese beiden widersprüchlichen Ziele zu lösen? Eine Möglichkeit ist ein zweistufiger CI-Prozess:

  1. Die deterministische Phase. Nutzt ein Pipfile.lock in Ihrem Repository, sodass es vollständig reproduzierbar ist.
  2. Die nichtdeterministische Phase. Führt pipenv update und führt dann die Tests aus, so dass die neuesten Ihrer Abhängigkeiten abgerufen werden (was im Grunde das gleiche ist wie das Verhalten ohne Sperrdatei, denke ich?).

@tsiq-oliverc Um deterministische Builds zu erhalten, würde ich an folgendes Setup denken:

  • pypi-Cache-Auftrag erstellen: Einmal ausführen und eine Form von pypi-Index-Cache erstellen (als Verzeichnis von Dateien oder ähnlichem)
  • Bibliothekstestjob: Verwenden des Pypi-Cache, aber Vermeiden von pipenv

Die Verwendung von pipenv für die Installation ist ähnlich wie die Installation der Bibliothek selbst, aber es ist definitiv anders, weil es ein anderer Code ist, der die Arbeit erledigt.

pypi-Cache-Job erstellen

$ git clone <repo_url> <project_dir>
$ cd <project_dir>
$ pip install pipenv
$ $ # clean pypi cache and make it ready to cache somehow - not described here
$ pipenv install -e .[test]
$ # if we need extra testing packages in pipenv
$ pipenv install <extra_test_packages>
$ # record current requirements expressed in `Pipfile.lock`
$ pipenv lock
$ # if needed, record the `Pipfile.lock` somewhere

Ausgaben eines solchen Jobs sind:

  • Pipfile.lock als aufgezeichnete Abhängigkeiten (kann Entwicklern helfen, die Umgebung leicht zu reproduzieren)
  • vorgefüllter lokaler Pypi-Cache

Bibliothekstestjob

es gibt Phasen:

  • Konfigurieren Sie die Umgebung, um tox , pip usw. zu erzwingen, indem Sie nur unseren lokalen Pypi-Cache verwenden
  • Führen Sie die CI-Tests aus (vermeiden Sie die Verwendung von pipenv )

was wir bekommen

  • Bibliothek wird in deterministischer Umgebung getestet
  • Bibliothek wird getestet inkl. es ist die Fähigkeit, sich selbst zu installieren
  • Pipfile.lock zeichnet pypi-Pakete auf, die verwendet wurden, um die Bibliothek zu installieren. Es kann verwendet werden, um die Umgebung am Entwicklerstandort zu reproduzieren.
  • Anpassung an aktualisierte Pakete auf (evtl. externem) pypi ist einfach (der "pypi Cache-Auftrag erstellen" erneut ausführen) und erfolgt kontrolliert (der Inhalt von pypi wird inkl. Hashes aufgezeichnet)

Ein weiterer Vorteil ist, dass dieses Setup keine Entwickler benötigt, die Pipfile oder Pipfile.lock pflegen. Auch das Ausführen der Tests in verschiedenen Kontexten ist immer gleich ( Pipfile.lock wird immer im gegebenen Kontext neu erstellt).

Was noch fehlt (und getan werden kann)

Der Pypi-Cache ist der Teil, der etwas Forschung erfordert. Ich denke, ein einfaches Verzeichnis würde ausreichen und vielleicht ist pipenv bereits bereit, dabei zu helfen. Vielleicht ist Ausgabe #1731 der fehlende Teil.

Als Paket, das die Abhängigkeitsauflösung durchführt, verlassen sich viele unserer eigenen Tests auf deterministische Builds – das heißt, wir nehmen bekannte Dinge und erwarten einen aufgelösten Graphen. Dafür verwenden wir pytest-pypi .

Ich liebe die lebhafte Diskussion zu diesem Thema. Ich denke, die Nuance ist wichtig und Sie sollten immer sowohl gegen bekannte als auch gegen nicht fixierte Abhängigkeiten testen

Sie sollten immer sowohl gegen bekannte als auch gegen ungepinnte Abhängigkeiten testen

Ich unterstütze diesen Vorschlag. Es ist eine gute Idee, immer einen expliziten "bekannten guten Zustand" für reproduzierbare Builds zu haben und das Debuggen zu vereinfachen, falls ein Update etwas kaputt macht, sowie sicherzustellen, dass neuere Neben-/Bugfix-Versionen ebenfalls funktionieren.

(Meiner ganz persönlichen Meinung nach wäre die Idealsituation, dass der Paketmanager standardmäßig die neuesten Minor-Versionen installiert, damit Bibliotheken immer die konkreten Abhängigkeitsversionen angeben können, mit denen sie getestet wurden, aber ich merke, das ist eine sehr umstrittene Meinung und erfordert jeden semver folgen.)

@Moritz90 @techalchemy @uranusjr @tsiq-oliverc

Hier ist meine Zusammenfassung aus der vorherigen Diskussion.

Besondere Probleme und Lösungsvorschläge

Viele Ausführungskontexte – wer verwaltet Pipfile.lock Datei(en)?

Jedes unterstützte Betriebssystem und Python-Interpreter trägt zur Matrix möglicher Ausführungskontexte bei.

ZB unterstützt Flask (zumindest CI-Sachen im Repository sichtbar):

  • Betriebssystem Windows (Python 2.7 und Python 3.6)
  • Linux (python 2.7, 3.4, 3.5, 3.6, nightly, pypi)
  • OSX (py - nicht sicher, ob es mehr Versionen gibt)

Es macht 9 verschiedene Ausführungskontexte, die sich unterscheiden können.

Jeder Ausführungskontext kann unterschiedliche Pipfile.lock .

Wer soll sie pflegen?

Optionen sind:

  • Lassen Sie Entwickler dies manuell tun (KEINE WEISE)
  • Pflegen Sie nur ein Pipfile.lock für die Hauptentwicklungsplattform (welche Plattform wird gerne ignoriert?)
  • Erstellung über CI automatisieren (JA)

Vorschlag: Lassen Sie CI die Datei mit pipenv install -e . generieren. Fügen Sie es nicht in das Repo ein, helfen Sie Entwicklern, die richtigen Pipfile.lock als Ergebnis automatisierter Builds auszuwählen.

Entwickler brauchen eine vorhersehbare Umgebung

Beim Beheben eines Problems, das durch Änderungen der Abhängigkeiten von pypi verursacht werden kann, benötigen Entwickler möglicherweise einfache Mittel, um die Umgebung aus dem fehlgeschlagenen Test zu reproduzieren.

Vorschlag:

  • Bei vielen Paketen sind die Änderungen der pypi-Abhängigkeiten so selten, dass sie kein wirkliches Problem darstellen
  • Um die Umgebung selbst zu reparieren, kann der Entwickler Pipfile.lock durch pipenv install -e . gefolgt von pipenv lock generieren.
  • Um die Umgebung aus einem fehlgeschlagenen Test zu replizieren, wählen Entwickler die Pipfile.lock aus dem fehlgeschlagenen Test aus.
  • todo: Beispiele zeigen, wie man Pipfile.lock in tox.ini anwendet.

CI muss gebrochene setup.py reveal aufdecken

Die Bibliothek setup.py kann beschädigt sein (fehlende Abhängigkeit in install_requires , fehlender Versionsspezifizierer usw.) und CI-Test darf ein solches Problem nicht verbergen (indem die ausgelassenen Abhängigkeiten selbst vorinstalliert werden).

Vorschlag:

  • Vertrauen Sie pipenv install -e . , um das gleiche Ergebnis wie bei der einfachen Installation zu erzielen (dabei gibt es derzeit einige Probleme).
  • Führen Sie einen einfachen Installationstest (ohne pipenv ) aus und vergleichen Sie möglicherweise, dass die resultierende Ausgabe von pip freeze eine Teilmenge dessen ist, was von pipenv installiert wird.

Aktualisierte pypi-Abhängigkeiten können Dinge zerstören, CI soll solche Verfolgungen erkennen

Einige Abhängigkeitsaktualisierungen können die Bibliothek beschädigen, die sie verwendet. CI wird Fehler bei einem solchen Problem erkennen.

Vorschlag:

  • Mindestens ein Test muss gegen die nicht angepinnte Version ausgeführt werden
  • Wenn CI immer neue Pipfile.lock generiert, ist dies kein Problem (da wir sowieso im nicht angehefteten Modus ausgeführt werden).

CI-Modi für verschiedene Bibliothekstypen

In allen vorgeschlagenen Modi habe ich versucht zu vermeiden, dass pipenv Dateien im Repository gespeichert werden, um Entwickler davon abzuhalten, dieses wirklich komplexe Zeug (Automatisierung!!!) zu pflegen.

Im Gegensatz zu meinem ursprünglichen Text verwenden der 2. und 3. Modus pipenv in CI-Skripten.

Modus: Laufen, Wald, Laufen!

Einfaches Paket mit einer geringeren Anzahl von Abhängigkeiten, die sich nicht oft ändern.

Laufen Sie einfach wie vor der Ära von pipenv und halten Sie die Dinge für uns einfach.

Seltene Fälle, in denen Abhängigkeiten zu Problemen führen, sind leicht zu beheben und rechtfertigen keine komplexere CI.

Modus: Generieren und versiegeln

Generieren Sie jedes Mal, wenn der CI-Test ausgeführt wird, ein neues Pipfile.lock das die momentan verwendete Umgebung vollständig beschreibt.

Das Pipfile.lock wird zum CI-Artefakt.

Wenn etwas schief geht, kann der Entwickler Pipfile.lock aus einem defekten Build auswählen, ihn lokal anwenden und die Tests und Reparaturen durchführen.

Wenn jemand bereitstellen möchte, kann Pipfile.lock aus dem letzten erfolgreichen Build verwendet werden.

Modus: Eiszeit

Wenn das Ändern von Abhängigkeiten ein echtes Problem ist, erstellt CI einmal Pipfile.lock und verwendet es für einen bestimmten Zeitraum (einen Monat?).

Dies erschwert das CI-Setup, da es mindestens zwei verschiedene Jobs geben muss (einer generiert Pipfile.lock , der andere wendet ihn an und verwendet ihn in Tests).

Achtung: Pipfile.lock muss auch aktuell aktualisiert werden, setup.py ändert Abhängigkeiten.

Beachten Sie, dass für Ice Age Scrat der Eichhörnchen-Testtyp erforderlich ist, der den eingefrorenen Status ignoriert und gegen ungepinnte Versionen prüft.

Schlußbemerkungen

Wie man sieht, wächst der Determinismus und die Komplexität von Modus zu Modus.

Mein Vorschlag wäre:

  • start einfach ("Run, Forrest, Run"). Sie gewinnen an Effizienz und Geschwindigkeit.
  • Wenn die Dinge aufgrund sich ändernder Abhängigkeiten zu komplex werden, fahren Sie mit "Generieren und Versiegeln" fort. Sie gewinnen Wiederholbarkeit in der lokalen Umgebung.
  • Wenn die Dinge wirklich schlecht sind, gehen Sie in den "Ice Age"-Modus. Sie gewinnen (vorübergehenden) Determinismus.

Alle Gewinne kosten etwas.

Wenn das Ziel hier darin besteht, die Ratschläge in den Dokumenten zu aktualisieren, dann fühlt es sich ehrlich gesagt unverantwortlich an, etwas dramatisch anderes zu sagen als "Befolgen Sie standardmäßig die Best Practices (reproduzierbare Builds), bis Sie keine andere Wahl haben".

@vlcinsky Unter der Überschrift "Modus: Generieren und versiegeln" kann es sinnvoll sein zu erwähnen, dass das letzte erfolgreiche Pipfile.lock immer erhalten bleiben sollte, zB indem es als Jenkins-Artefakt deklariert wird. Mit dieser Änderung wäre es in Ordnung, dieses Setup für die meisten Projekte zu empfehlen. Wie @tsiq-oliverc würde ich den ersten Modus überhaupt nicht empfehlen.

Je mehr ich darüber nachdenke, desto mehr habe ich das Gefühl, dass diese Dokumentation ein Abschnitt darüber wird, warum die Verwendung von pipenv für CI-Builds eine großartige Idee ist, selbst wenn Sie eine Bibliothek entwickeln.

@tsiq-oliverc Die überwiegende Mehrheit der allgemeinen Python-Pakete befindet sich im Modus "Run, Forrest, Run". Ich habe einigen dieser Pakete bei der Einführung von tox und pytest geholfen, weil ich der Meinung war, dass dies zu einer gegebenen Paketqualität beitragen würde und weil ich eine ziemlich klare Vorstellung hatte, wie es gut gemacht werden könnte.

Jetzt gibt es ein weiteres großartiges Tool und ich frage mich, wie man pipenv in allgemeinen Python-Projekten richtig einsetzt, um zur Qualität beizutragen. Ich möchte ein oder zwei gut funktionierende Rezepte finden, die gerechtfertigt und leicht zu befolgen sind.

Was würde ich zum Flask-Projekt sagen?

  1. Befolgen Sie standardmäßig die Best Practices (reproduzierbare Builds), bis Sie keine andere Wahl haben?
  2. 9 Pipfile.lock Dateien hinzufügen und Richtlinien für deren Aktualisierung einrichten?
  3. CI-Skripte für Travis und Appveyor so umgestalten, dass sie nach dem Ice Age-Modus in zwei Phasen funktionieren?
  4. Ändern Sie CI-Skripte für Travis und Appveyor, um Pipfile.lock Artefakte für Fälle zu generieren, in denen jemand einen fehlgeschlagenen Test auf seinem eigenen Computer reproduzieren muss?
  5. keine Kommentare, außer "Vielen Dank für Flask."

Ziel ist es, einen funktionalen Arbeitsstil zu finden. Wenn es auf doc endet, schön, wenn nicht, kein Problem.

@vlcinsky Ich würde sagen, (1) und (4) sollten die Empfehlung für solche Projekte sein. Während Sie ohne ein bereits vorhandenes Pipfile.lock die im Build verwendeten Versionen nicht im Voraus kennen (was außerhalb von Unternehmensumgebungen in Ordnung ist), erhalten Sie dennoch ein reproduzierbares Ergebnis, wenn Sie die Sperrdatei generieren und archivieren während des Aufbaus.

Bearbeiten : Die tl; dr-Version meiner Empfehlung wäre:

  • Stellen Sie immer sicher, dass Ihre Builds reproduzierbar sind, unabhängig davon, ob Sie eine Bibliothek oder eine Anwendung entwickeln. pipenv kann Ihnen dabei helfen, dieses Ziel zu erreichen.
  • Wenn Sie eine Anwendung entwickeln, übertragen Sie Pipfile.lock in Ihr Repository und verwenden Sie es für die Bereitstellung. (Dies ist bereits durch die vorhandene Dokumentation abgedeckt.)
  • Wenn Sie eine Open-Source-Bibliothek entwickeln, generieren Sie Pipfile.lock on-the-fly in Ihrem CI-Build und archivieren Sie es für später.
  • Wenn Sie eine Bibliothek entwickeln und in einer restriktiven Unternehmensumgebung arbeiten, behalten Sie die entsprechende Anzahl von Sperrdateien bei und verwenden Sie diese in Ihren CI-Builds.

(Natürlich sollte die eigentliche Dokumentation etwas mehr Details und Beispiele enthalten.)

@ Moritz90 Ich habe das "Generieren und Versiegeln" wie von Ihnen vorgeschlagen geändert.

Zu (1): leicht zu sagen, unmöglich auszuführen, ohne genauer zu sein.

Zu (4): ja, ich denke auch, dass "Generate and Seal" der praktikabelste Modus ist. Aber im Falle von Flask werde ich mich (zumindest im Moment nicht) nicht trauen.

Re vorhandene Pipfile.lock in Unternehmensumgebungen: Es muss irgendwie erstellt werden, entweder (halb)manuell oder automatisch. Ich schätze, in einer Unternehmensumgebung installiert man nicht direkt von öffentlichen pypi, sondern verwendet ein privates, das nur genehmigte Pakete bereitstellt ( devpi-server bietet dabei einen großartigen Service - mehrere Indizes, kontrollierte Volatilität veröffentlichter Pakete, Genehmigungen für externe Pakete usw.) Wenn der Prozess zum Erstellen von Pipfile.lock in einer solchen Umgebung läuft, kann er nur das verwenden, was genehmigt wurde. Wenn also dort eine neue Version erscheinen soll, muss jemand aufstehen und sie genehmigt machen. Der folgende CI-Build wird testen, ob die Dinge nicht kaputt gehen. Und mit pipenv check Test von Sicherheitsproblemen auch automatisiert werden.

Ich denke, ein solcher Workflow wäre sicherer als jemand, der ihn (halb) manuell erstellt. Aber mein Wissen über die Unternehmensumgebung ist sehr begrenzt.

Hallo Pipenv-Team. Ich teile viel von dem, was in diesem Text gesagt wird, es hilft jedem Entwickler, die Einschränkungen von Pipfile/pipenv beim Entwickeln einer Bibliothek besser zu verstehen. Ich möchte diesen Text oder einen Teil davon in die offizielle pipenv-Dokumentation integriert sehen.

Ich habe folgende Änderung, die ich gerne besprechen möchte:

Für unser internes Python - Paket, komplett wiederverwendbar, auf unserer internen pypi veröffentlicht, etc, und auch für meine eigenen Python - Pakete (zB: cfgtree , txrwlock , pipenv-to-Anforderungen ), verwende ich ein Paket , dass einige schon wissen oder sogar nutzen , das diese Details abstrahiert und das Leben von Python-Entwicklern einfacher macht: PBR.
PBR liest grundsätzlich requirements.txt im Stammordner eines Distributionspakets und fügt es in das install_requires des setup.py . Der Entwickler muss lediglich ein requirements.txt mit losen Abhängigkeitsdeklarationen pflegen. Bis die Unterstützung von Pipfile offiziell in PBR integriert ist, muss ich pipenv-to-requirements verwenden , die automatisch requirements.txt aus Pipfile generieren, damit beide synchronisiert und beide festgeschrieben werden im Quellcode, und PBR führt die Injektion korrekt aus, nachdem das Verteilungspaket erstellt wurde. Ich denke, man könnte pipenv , um dieses requirements.txt zu generieren

Ich arbeite an einer Unterstützung von Pipfile für PBR, damit es die Pipfile (und nicht die Sperrdatei) lesen und in install_requires injizieren kann, wie es bei requirements.txt Fall ist

Ich weiß nicht, ob es andere ähnliche Pakete gibt, weil es auch andere Dinge macht, die die Leute vielleicht nicht wollen (Version aus der Git-Historie, automatische Generierung von AUTHORS und ChangLog).

Aber am Ende finde ich es wirklich so einfacher, eine Python-Bibliothek zu schreiben, zu warten und zu verwalten, dass ich traurig wäre, diese Erfahrung nicht zu teilen. Ich bewerbe es als die "empfohlene" Art, moderne Python-Bibliotheken in meinem Unternehmen zu schreiben.

Ich vermute, dass es wie "Betrügen" bei allen Schwierigkeiten bezüglich Bibliothek und Pipenv ist, aber am Ende ist die Arbeit getan und die Entwickler sind glücklich, sie bis jetzt zu verwenden. Ein Teil des Python-Trainings, das ich neuen Python-Entwicklern in meinem Unternehmen gebe, beinhaltet, zuerst eine Python-Bibliothek zu schreiben, die install_requires manuell verwaltet, und dann zu PBR zu wechseln, um zu sehen, wie es einfacher wird ( und ehrlich gesagt bin ich ein Fan der semantischen Commit-Funktion von pbr, um automatisch das richtige Semver-Versions-Tag zu erstellen).

Ein Grund für die Deklaration der Bibliotheksabhängigkeiten mit einer dedizierten Datei auch für Bibliotheken ist die Möglichkeit, Tools wie readthedocs oder pyup verwenden zu können (auch wenn pyup mehr Sinn macht, wenn es mit einer Anwendung verknüpft wird).

Ich möchte diese Methode nicht unbedingt als "Standard"-Methode für Python-Pakete bewerben, es ist tatsächlich die "OpenStack" -Methode, aber ich würde meine Erfahrungen teilen, und wenn andere ähnliche oder widersprüchliche Erfahrungen haben, werde ich es sein Ich freue mich, sie zu hören und meinen Standpunkt zu aktualisieren.

Team, was halten Sie von einer Art "Community"-Abschnitt in der Dokumentation? Damit Benutzer wie ich seine Erfahrungen mit seiner Verwendung von pipenv teilen können, ohne unbedingt die volle Unterstützung des pipenv-Teams zu haben?

PS: Ich kann dies in ein spezielles Thema verschieben, wenn Sie diesen Thread nicht verschmutzen möchten

@vlcinsky (1) ist sehr einfach auszuführen - legen Sie Ihre Sperrdatei in Ihr Repository.

Ich denke, Sie meinen stattdessen: Es ist unmöglich, konkrete Ratschläge zu geben, wenn diese grundlegende Strategie nicht mehr ausreicht. Das ist sicher richtig, aber das liegt daran, dass das konkrete Problem wahrscheinlich von Fall zu Fall unterschiedlich ist.

Oder anders ausgedrückt: Die Lösung hängt davon ab, welche zusätzlichen Garantien Sie für Ihren CI-Workflow wünschen.

@gsemet weißt du was? Alle meine Python-Pakete, die in den letzten zwei Jahren erstellt wurden, basieren auf pbr - es ist wirklich großartig. Und ich verfolge Ihre Versuche, Pipfile in pbr zu unterstützen, wann immer ich kann (einige Daumen hoch, Stimmen usw.).

In diesem Fall (Suche nach pipenv Mustern und Antimustern für allgemeine Python-Bibliotheken) habe ich pbr aus zwei Gründen absichtlich weggelassen:

  • es würde die konzeptionelle Diskussion komplexer machen
  • manche Leute mögen pbr aus anderen Gründen nicht (du hast sie erwähnt) und es würde die Diskussion wahrscheinlich ablenken

Auf der anderen Seite freue ich mich schon sehr auf ein Rezept von dir für PBR-Liebhaber. Ich werde es lesen.

@tsiq-oliverc du hast den Nagel getroffen: Lege deine Lockfile in dein Repo

Das ist genau das Problem, das mich motiviert hat, dieses Thema zu starten. Wenn Sie den Anfang dieses Problems noch einmal lesen, finden Sie eine Beschreibung einiger Fälle, in denen das Hinzufügen von Pipfile.lock Ihre CI-Tests unterbrechen kann (entweder den Build-Lauf unterbrechen oder Probleme ausblenden, die sonst erkannt würden, oder falsche Abhängigkeiten installieren für gegebenen Kontext...).

Wenn Sie mir ein Repo zeigen, wo dies richtig gemacht wird (allgemeine Python-Bibliothek), würde ich mich freuen. Oder ich würde aufzeigen, welche Risiken es gibt oder welche Dinge unfertig sind.

Cool ! Ich pflege auch

@vlcinsky Richtig, also lass uns die spezifischen Probleme aufzählen und Lösungen dafür finden 😄 (Ich kenne keine hochwertige Bibliothek, die Pipenv verwendet, aber das liegt hauptsächlich daran, dass ich nicht nachgesehen habe.)

Soweit ich das beurteilen kann, sind dies die spezifischen Symptome in Ihrem ursprünglichen Beitrag:

  • Ausblenden defekter setup.py-Abhängigkeiten. Das hört sich nach einem nicht an - pipenv install -e . , richtig?
  • Abhängigkeiten sind wahrscheinlich für verschiedene Python-Versionen oder in einem anderen Betriebssystem ungültig. Ich kann sehen , dass dies könnte ein Problem sein, aber könnten Sie ein konkretes Beispiel vorsehen , wenn dies in der Praxis von Bedeutung ist? (im Kontext einer Lockfile)
  • Entwickler sind gezwungen zu aktualisieren ... wenn andere Bibliotheken aktualisiert werden und innerhalb der Bibliothek verwendet werden können. Dazu sind sie nicht gezwungen . Sie tun dies, wenn sie garantieren möchten, dass ihre Bibliothek mit Version n+1 und nicht mit Version n ihrer Abhängigkeit arbeitet. Beachten Sie jedoch, dass ich bereits eine Alternative vorgeschlagen habe, die das Beste aus beiden Welten bietet.
  • Im Wettbewerb mit Tox. Ich habe keine Ahnung von Tox. Aber ja, die gleichzeitige Verwendung von zwei Tools zur Verwaltung Ihrer Abhängigkeiten klingt nach einem Rezept für eine Katastrophe. Ich würde sagen, verwenden Sie diejenige, die für diese spezielle Aufgabe überlegen ist.
  • Pipenv schlägt fehl. Das hört sich nach einem weiteren Problem an - Sie können einfach die Version von Pipenv anheften (das ist meine aktuelle Lösung, genau wie ich mein Docker-Image, meine Version von Pip usw. anhefte).

@tsiq-oliverc Ich muss sagen, Ihre Kommentare haben mich inspiriert und ich weiß, dass sie zu einer höheren Reproduzierbarkeit der vorgeschlagenen Lösung beigetragen haben.

Folgendes bezieht sich auf Ihren Vorschlag, die Sperrdatei ( Pipfile.lock ) in das Repository zu legen, um die Wiederholbarkeit zu gewährleisten:

re Ausblenden defekter setup.py-Abhängigkeiten. . Die pipenv install -e . folgen dem, was ich vorschlage, aber beachte, dass dies keine Verwendung von Pipfile.lock , sondern eine Methode, um es (neu) zu erstellen. Wenn jemand Pipenv.lock behält und damit virtualenv erstellt, bevor das Paket installiert wird, liegt das Problem vor.

re Abhängigkeiten sind wahrscheinlich für verschiedene Python-Versionen oder in einem anderen Betriebssystem ungültig . Es gibt viele Beispiele: doit das für Python 2.7 installiert wurde, muss eine ältere Version sein, da die neuere Version die Unterstützung für Python 2.x eingestellt hat. watchdog Abhängigkeit erfordert plattformabhängige Bibliotheken: inotify unter Linux, etwas anderes unter Windows, etwas anderes unter OSX. Mein ehemaliger Kunde sagte immer "Das wird nie passieren" und in 50% der Situation geschah dies innerhalb von 2 Wochen. Dies ist nicht die beste Vorgehensweise für CI-Skripte.

re Entwickler sind gezwungen zu aktualisieren .. Stellen Sie sich eine Open-Source-Bibliothek mit 15 Mitwirkenden vor. Es ist so leicht zu vergessen, Pipfile.lock von einem Neuling oder müden Core-Entwickler zu regenerieren. ZB im maya Paket wurde ich gebeten, Pipfile.lock neu zu generieren, da eine neue Abhängigkeit zu setup.py hinzugefügt wurde. War das nötig? Habe ich es richtig aktualisiert? Habe ich es für alle unterstützten Ausführungskontexte aktualisiert? Antworten sind nein, nicht sicher, nein. Wie auch immer, danke für Ihren Vorschlag (er hat mich zu der neben Ihrem Kommentar beschriebenen Lösung inspiriert).

re Im Wettbewerb mit tox : Tox ermöglicht die Erstellung mehrerer virtueller Umgebungen und die Automatisierung der darin ausgeführten Tests. Typisch tox.ini definiert verschiedene virtuelle Umgebungen für Python 2.7, 3.4, 3.5, 3.6 und alle anderen, die Sie benötigen, und ermöglicht die Installation des Pakets dort und die Ausführung der Testsuite. Es ist ein etabliertes Powertool von ernsthaften Testern. pipenv ist nicht das richtige Werkzeug für diesen Zweck, kann aber die Installation der benötigten Dinge stören. In gewisser Weise bin ich Ihrem Rat gefolgt und habe vorgeschlagen, nach Möglichkeit ein überlegenes Werkzeug (Tox) über pipenv zu verwenden.

re Pipenv schlägt fehl. Das ist wirklich schade. Ich hatte einen CI-Test (tox-basiert), der auf localhost gut lief, aber wenn er über Travis ausgeführt wurde, schlug er aufgrund eines pipenv Problems fehl. Wenn ich es jetzt verwenden möchte, hilft das Anheften nicht, bis der Fix veröffentlicht wird. Aber so geht es - ich warte.

Beachten Sie, dass einige Teile meines ursprünglichen Beitrags aktualisiert werden müssen, wie es scheint, die Verwendung von pipenv in CI-Skripten hat ihren berechtigten Platz ("Versiegelung" der virtualenv-Konfiguration für eine mögliche spätere Verwendung).

@tsiq-oliverc Während mir Ihr Vorschlag, sowohl gegen das "bekannte Gut" als auch gegen die neuesten Versionen zu testen, anfangs gefiel, fällt es mir immer schwerer, den Aufwand zu rechtfertigen, je mehr ich darüber nachdenke. Ich denke, Sie sollten sich für das eine oder das andere entscheiden, nicht für beides.

Das einzige, was Sie gewinnen, ist, dass Sie sofort wissen, ob ein Fehler durch ein Abhängigkeitsupdate oder eine Codeänderung verursacht wurde. Aber Sie können dasselbe erreichen, indem Sie einfach separate Commits durchführen (wenn Sie gesperrte Abhängigkeiten manuell aktualisieren) oder versuchen, den Fehler mit der neuesten Sperrdatei eines erfolgreichen Builds zu reproduzieren (wenn Sie immer die neuesten Versionen verwenden). Und in eingeschränkten Umgebungen kann man sowieso nicht "einfach aktualisieren"...

@vlcinsky Während ich Ihrem allgemeinen Punkt zu den Unterschieden zwischen Umgebungen zustimme, klingt das Argument "eine Sperrdatei pro Konfiguration" für mich wie ein Strohmann. In der Praxis können Sie die Sperrdateien zumindest für einige Umgebungen freigeben.

Eine noch offene Frage, die noch niemand beantwortet hat, ist der Umgang mit dem Fall, in dem Sie beide in unterschiedlichen Umgebungen testen und Ihre Abhängigkeiten sperren müssen. Ich muss zugeben, dass ich nichts über tox weiß, außer dass es existiert, aber es scheint, als ob zwischen tox und pipenv eine Art Klebstoff benötigt wird das löst dieses problem irgendwie.

@Moritz90

Treffen mit dem Strohmann

In Bezug auf zu viele Varianten von Pipfile.lock die als Strohmann dienen (um andere von meinem Feld fernzuhalten):

Flasche

Ich habe ein flask Projekt genommen (da es sehr ausgereift ist) und Tox-Tests durchgeführt:

Hier sehen Sie eine Liste der getesteten Varianten (nur lokal unter Linux, multiplizieren Sie sie mit 3, da Windows und OSX die gleichen Tests durchführen, aber zu unterschiedlichen Umgebungen führen können).

Es gibt 16 verschiedene Testläufe auf einem Betriebssystem, 5 davon sind fehlgeschlagen, da ich sie nicht installiert habe (das ist in Ordnung), einer befasst sich mit dem Erstellen von Dokumenten (erfordert eine importable Bibliothek) und ein anderer deckt (was auch eine importierbare Bibliothek erfordert) ):

  coverage-report: commands succeeded
  docs-html: commands succeeded
  py27-devel: commands succeeded
  py27-lowest: commands succeeded
  py27-simplejson: commands succeeded
  py27: commands succeeded
  py35: commands succeeded
  py36-devel: commands succeeded
  py36-lowest: commands succeeded
  py36-simplejson: commands succeeded
  py36: commands succeeded
ERROR:   py34: InterpreterNotFound: python3.4
ERROR:   pypy-devel: InterpreterNotFound: pypy
ERROR:   pypy-lowest: InterpreterNotFound: pypy
ERROR:   pypy-simplejson: InterpreterNotFound: pypy
ERROR:   pypy: InterpreterNotFound: pypy

Für jede der erstellten virtuellen Umgebungen habe ich eine requirements.txt Datei von pip freeze > {venv_name}.txt

Dann berechnete Hashes für die Dateien, sortiert nach Hash-Werten, damit alle gleich gruppiert werden. Hier kommt der Strohmann:

b231a4cc8f30e3fd1ca0bfb0397c4918f5ab5ec3e56575c15920809705eb815e  py35.txt
b231a4cc8f30e3fd1ca0bfb0397c4918f5ab5ec3e56575c15920809705eb815e  py36.txt
cdf69aa2a87ffd0291ea65265a7714cc8c417805d613701af7b22c8ff2b5c0e4  py27-devel.txt
dfe27df6451f10a825f4a82dfe5bd58bd91c7e515240e1b102ffe46b4c358cdf  py36-simplejson.txt
e48cd24ea944fc9d8472d989ef0094bf42eb55cc28d7b59ee00ddcbee66ea69f  py36-lowest.txt
f8c745d16a20390873d146ccb50cf5689deb01aad6d157b77be203b407e6195d  py36-devel.txt
053e107ac856bc8845a1c8095aff6737dfb5d7718b081432f7a67f2125dc87ef  docs-html.txt
45b90aa0885182b883b16cb61091f754b2d889036c94eae0f49953aa6435ece5  py27-simplejson.txt
48bd0f6e66a6374a56b9c306e1c14217d224f9d42490328076993ebf490d61b5  coverage-report.txt
564580dad87c793c207a7cc6692554133e21a65fd4dd6fc964e5f819f9ab249c  py27.txt
8b8ff4633af0897652630903ba7155feee543a823e09ced63a14959b653a7340  py27-lowest.txt

Beängstigend, nicht wahr? Von allen Tests teilen nur zwei die gleichen eingefrorenen Abhängigkeiten.

Dies ist die Realität einer allgemeinen Python-Bibliothek mit einer guten Testsuite. Sie werden jetzt wahrscheinlich zugeben, dass dies etwas ganz anderes ist als die Python-Bibliothek, die in einer Unternehmensumgebung getestet wurde.

Jinja2

Überprüfen von jinja2 , was ein viel einfacheres Tier zu sein scheint:

  coverage-report: commands succeeded
  py26: commands succeeded
  py27: commands succeeded
  py33: commands succeeded
  py35: commands succeeded
  py36: commands succeeded
ERROR:   docs-html: commands failed
ERROR:   py34: InterpreterNotFound: python3.4
ERROR:   pypy: InterpreterNotFound: pypy

Wenn ich Prüfsummen sehe, bin ich überrascht, dass sich py27.txt und py26.txt unterscheiden:

047a880804009107999888a3198f319e5bbba2fa461b74cfdfdc81384499864e  py26.txt
047a880804009107999888a3198f319e5bbba2fa461b74cfdfdc81384499864e  py33.txt
047a880804009107999888a3198f319e5bbba2fa461b74cfdfdc81384499864e  py35.txt
047a880804009107999888a3198f319e5bbba2fa461b74cfdfdc81384499864e  py36.txt
48bd0f6e66a6374a56b9c306e1c14217d224f9d42490328076993ebf490d61b5  coverage-report.txt
743ad9e4b59d19e97284e9a5be7839e39e5c46f0b9653c39ef8ca89c7b0bc417  py27.txt

@vlcinsky Das ist in der Tat beängstigend. Ich frage mich, ob Flask ein Sonderfall ist oder ob das tatsächlich die Norm ist, aber Sie haben mir definitiv das Gegenteil bewiesen.

Ich hoffe jetzt, dass unsere Python-Bibliothek nicht eines Tages unter dem gleichen Problem leiden wird und dass die Unterschiede dort besser überschaubar sind.

@ Moritz90 Ihre interne Bibliothek bedient ein ganz anderes Publikum, sodass Sie es sich leisten können, den Ausführungskontext viel enger zu halten.

Allgemeine Python-Bibliotheken sind oft flexibel und konfigurierbar, zB erlaubt Flask die Installation und Nutzung alternativer Json-Parser, was durch einen separaten Testlauf abgedeckt wird.

Man kann viel über Testen und Toxen von Flasks tox.ini lernen

Die niedrigsten Testvarianten achten darauf, gegen die älteste Abhängigkeitsversion zu testen.

devel testet gegen die Entwicklungsversion der Kernabhängigkeiten.

Ich würde sagen, Flask ist auf der höheren Komplexitätsebene und weist eine sorgfältige Testsuite auf.

Die tox.ini von Pyramid zeigt eine ähnliche Anzahl von Umgebungen (sie zielen auch auf eine 100%ige Codeabdeckung ab).

mayas tox.ini ist sehr frisch (2 Tage) und einfach, auch hier gibt es 4 verschiedene Umgebungen und py27 unterscheidet sich in den eingefrorenen Anforderungen von py35 und py36.

@Moritz90
Zum Kleber zwischen Pipenv und Tox

  • pipenv --man zeigt einige Anweisungen, wie man pipenv innerhalb von tox.ini Befehlen verwendet
  • tox-pipenv versucht, eine zusätzliche Integration bereitzustellen, aber das verwirrt mich im Moment.

tox.ini Datei pipenv einschließt.

pipenv hat eine großartige Funktion, die, wenn sie in einer bereits aktivierten virtuellen Umgebung ausgeführt wird (was bei toxbasierten Tests der Fall ist), in einer bestimmten virtuellen Umgebung installiert wird. Das ist wirklich schön.

Da wir wahrscheinlich Pipfile.lock generieren müssen, müssen einige zusätzliche Anstrengungen unternommen werden, um es zu bekommen und an die richtige Stelle zu verschieben (ag in .tox/py36/Pipfile.lock , um ein Überschreiben durch den folgenden Test zu verhindern. Dies ist möglich, aber mit einigen Vereinfachungen wäre willkommen.Vielleicht würde es ein Trick mit der Umgebungsvariablen für den Standort von Pipfile noch einfacher machen.

@vlcinsky

  • setup.py - Ich bin pipenv install -e . einmal aus, sodass setup.py jetzt über Ihre Sperrdatei verfolgt wird. Führen Sie dann pipenv install wenn Sie setup.py neue Pakete hinzufügen.
  • Entwickler, die vergessen, die Sperrdatei zu aktualisieren - pipenv --deploy entwickelt, um dies abzufangen . Führen Sie es in Ihrem CI aus!
  • Pipenv schlägt fehl - vereinbart, wenn es Fehler im Tool gibt, ist das scheiße. Aber Fehler werden in der Regel behoben. Das ist kein Grund eine ganze Philosophie wegzuwerfen 😞
  • Tox

    • Wenn Tox gut für die Verwaltung von Tests ist, ist das großartig. Wenn es sich auch hervorragend zum Verwalten von Paketen und deterministischen Builds eignet, ist das noch besser.

    • Aber wenn das wahr wäre, gäbe es für Pipenv keinen Grund zu existieren. Ich kann also nur davon ausgehen, dass es bei Tox eine Art Einschränkung gibt.

    • Ähnlich wie oben klingt der Zustand der Welt heute (das Fehlen einer guten Interoperabilität) nicht nach einem Grund, die Philosophie abzulehnen.

  • Mehrere Umgebungen

    • Es ist klar, dass es hier zumindest einige Sonderfälle wie Flask gibt.

    • Ich habe keinen besseren Vorschlag für mehrere Lockfiles (obwohl es in dieser Hinsicht vielleicht eine zukünftige Funktion für Pipenv gibt?)

    • Aber selbst in diesem Fall bin ich immer noch nicht davon überzeugt, dass die Verwaltung mehrerer Lockfiles in der Praxis ein Problem darstellt. Im schlimmsten Fall könnten Sie ein einfaches Skript update-all-lockfiles.sh lokal erstellen und pipenv --deploy auf Ihrem CI ausführen, um Fehler abzufangen.


@ Moritz90 -


Allgemeiner gesagt wäre es gut, sicherzustellen, dass sich dieser "Vorschlag" auf die Dinge konzentriert, die eigentlich schwierige Probleme sind (meiner Ansicht nach (A) mehrere Umgebungen bedienen, (B) Änderungen in Upstream-Abhängigkeiten abfangen wollen). Es sollte nicht auf vorübergehenden Dingen (Bugs in Pipenv) oder möglichen Missverständnissen bezüglich der Verwendung des Tools basieren.

Aber selbst für diese "harten" Probleme sollte das Framing so aussehen: "In einigen komplexen Randfällen kann es sein, dass ein grundlegender Pipenv-Workflow nicht ausreicht, also sind hier einige Dinge zu beachten". IMO, es sollte nicht als Standardansatz bezeichnet werden (da die meisten Leute diese Bedenken nicht haben).

Das von @vlcinsky bereitgestellte Dokumentationsbeispiel würde einfacher und weniger verwirrend, wenn Pipenv/Pipfile die Behandlung von lib-dependencies , app-dependencies und dev-dependencies zulassen würde. Dokumente könnten etwa so aussehen:

Verwenden Sie die Option lib-dependencies wenn es sich bei Ihrem Paket um eine gemeinsam genutzte Bibliothek handelt. Beispiel Pipfile :

[lib-dependencies]
some-lib=="*"
another-lib=="*"
yet-another-one==">=1.0"

[dev-dependencies]
some-dev-tool=="1.1"

Bei Shared Libraries ist es wichtig, die Versionsbereiche unter [lib-dependencies] so breit wie möglich zu halten, um Versionskonflikte auf dem Consumer-System zu vermeiden.

Wenn Ihr Paket eine Anwendung ist (die von pipenv auf dem Zielsystem installiert werden soll), die genaue Abhängigkeitsversionen erfordert, sollten Sie die Option [app-dependencies] . Beispiel Pipfile :

[app-dependencies]
some-lib=="1.0.12"
another-lib=="1.*"
yet-another-one=="2.0"

[dev-dependencies]
some-dev-tool=="1.1"

/Enddokument-Beispiel

Ein anderer Ansatz könnte ein Pipfile.lib und ein Pipfile.app .

Ich denke, so etwas würde die Notwendigkeit eines Teils von Anti-Pattern-Abschnitten und Tools von Drittanbietern überflüssig machen, um die Lücke zu füllen.

Pipenv-Packaging-Tool zu nennen, ist irreführend, wenn man erwartet, dass es Python-Bibliotheken erstellt oder stark an deren Erstellung beteiligt ist.

Ich denke, das ist ein echtes Problem, das zu viel Verwirrung führt. Vor allem bei Leuten, die es gewohnt sind, Manager in anderen Programmiersprachen (zB JS, Rust, Elm) zu packen. Es dauerte mehrere Monate und ich habe gelegentlich Github-Probleme gelesen, bis mir klar wurde, dass ich Pipenv und setup.py falsch verwendet habe.

@luxus

Ihr [lib-dependencies] oder Pipfile.lib ist das, was wir heute in Pipfile (als abstrakte Abhängigkeiten - so breit wie möglich).

Ihre [app-dependencies] oder Pipfile.app haben wir in Pipfile.lock (als spezifische Abhängigkeiten).

pipenv und seine Dateien können in zwei verschiedenen Situationen verwendet werden - beim Entwickeln einer Bibliothek oder beim Vorbereiten einer Anwendungsbereitstellung, aber wahrscheinlich nicht für beides gleichzeitig. Aus diesem Grund sehe ich keine triftigen Gründe dafür, zusätzliche Abschnitte in Pipenv hinzuzufügen. Es liegt in der Verantwortung der Entwickler zu wissen, welchen Zweck die Pipfile erfüllen werden.

Ich denke, das ist ein echtes Problem, das zu viel Verwirrung führt. Vor allem bei Leuten, die es gewohnt sind, Manager in anderen Programmiersprachen (zB JS, Rust, Elm) zu packen. Es dauerte mehrere Monate und ich habe gelegentlich Github-Probleme gelesen, bis mir klar wurde, dass ich Pipenv und setup.py falsch verwendet habe.

Einverstanden. Die dreiteilige Lösung ist auch eine sehr interessante Lösung, die ich noch nie in Betracht gezogen habe, und sie scheint richtig und (überraschend!) einfach zu sein.

Da ich selbst einen Python-Hintergrund habe, hatte ich immer das Gefühl, dass Nodes package.json es falsch macht (Rust ist besser, weil es einen Compiler und einen Linker hat und dies zu einem späteren Zeitpunkt beheben kann). App- und lib-Abhängigkeiten auf die gleiche Weise zu behandeln, funktioniert für eine Skriptsprache wie Python zumindest im abstrakten Sinne einfach nicht – dh es könnte für Sie funktionieren, aber ein generisches Tool wie Pipenv kann dies nicht, weil es so sein muss generisch.

Obwohl ich die dreiteilige Lösung im Konzept mag, ist sie immer noch eine ziemlich inkompatible Änderung des bestehenden Ökosystems. Es gibt bereits setup.py, setup.cfg und (möglicherweise) pyproject.toml, die diesen Platz füllen. Wenn Pipenv (genauer gesagt Pipfile) in den Space einziehen möchte, muss es sich mit verwandten Projekten wie pip (die Bibliotheksunterstützung sollte idealerweise direkt von ihm unterstützt werden) und flit konsolidieren.

Wie ich in anderen Fragen zur Handhabung von lib/app-Abhängigkeiten erwähnt habe, muss diese Diskussion an pypa-dev (die Mailingliste) und/oder den PEP-Prozess eskaliert werden, damit sie von anderen Parteien und relevanten Personen besser gehört werden kann, bevor Pipenv (Pipfile) kann sich in alle Richtungen bewegen.

@vlcinsky

Ihre [lib-dependencies] oder Pipfile.lib ist das, was wir heute in Pipfile haben (als abstrakte Abhängigkeiten - so breit wie möglich).

Sorry, wenn das nicht klar war. Meine lib-dependencies sollen das sein, was die Leute derzeit in setup.py / install_requires . Vielleicht wäre pypi-dependencies ein besserer Name für das, was ich meinte.

@uranusjr

Es gibt bereits setup.py, setup.cfg und (möglicherweise) pyproject.toml, die diesen Platz füllen.

Pipenv (das Befehlszeilentool) könnte setup.py Schnittstelle verwenden. Nur der Abhängigkeitsabschnitt von setup.py müsste nach Pipfile verschoben werden. Zumindest in meiner Vorstellung :)

Wie ich in anderen Fragen zur Handhabung von lib/app-Abhängigkeiten erwähnt habe, muss diese Diskussion an pypa-dev (die Mailingliste) und/oder den PEP-Prozess eskaliert werden, damit sie von anderen Parteien und relevanten Personen besser gehört werden kann, bevor Pipenv (Pipfile) kann sich in alle Richtungen bewegen.

Ok, sorry für die Mühe ;) Wenn ich etwas Zeit finde, schreibe ich etwas für die Mailingliste.

Im Rahmen dieses Vorschlags würde ich jedoch vorschlagen, sich auf die derzeit möglichen Best Practices zu konzentrieren, anstatt in den Kaninchenbau zu gehen, einen neuen Workflow für die gesamte Python-Packaging-Community zu erarbeiten. Es wäre produktiver, innerhalb der aktuellen Einschränkungen eine Best Practice vorzuschlagen und dann die Diskussion über Verbesserungen zu beginnen.

@uranusjr - Ich komme aus einem "kompilierten" Hintergrund, also bin ich neugierig, warum das so ist?

Die gleiche Behandlung von App- und Lib-Abhängigkeiten funktioniert für eine Skriptsprache wie Python einfach nicht

@tsiq-oliverc Da die Best Practice der App erfordert, dass Sie Ihre Abhängigkeiten anheften, würden Bibliotheken auch ihre anheften, wenn sie dieselbe Quelle von Anforderungsdateien verwenden. Dies würde zu Problemen bei der Abhängigkeitsauflösung führen.

Sagen wir, meine App hat zwei Abhängigkeiten A und B, beide hängen von C ab, aber A-Pins v1, während B-Pins v2. Kompilierte Sprachen ermöglichen es der Toolchain, dies zur Kompilierzeit zu erkennen und auf viele Arten zu lösen. Rust macht dies zum Beispiel während der Linkzeit – Die ausführbare Enddatei würde zwei Kopien von C (v1 und v2) enthalten, wobei A und B jeweils mit ihnen verknüpft sind. Im C++-Land würde dies mit dynamischen Bibliotheken gelöst werden; die Symbolsuche erfolgt noch später (zur Laufzeit), aber die Idee ist dieselbe – der Compiler weiß, was Sie brauchen (von der verwendeten Schnittstelle) und kann entsprechend handeln.

Skriptsprachen können dies nicht, weil sie nicht wissen, was Sie wirklich tun möchten, bis sie den Anruf tatsächlich erreichen. Node umgeht dies, indem es immer davon ausgeht, dass die Abhängigkeiten inkompatibel sind (A und B erhalten immer ihr eigenes C, auch wenn die beiden Kopien identisch sind), aber das führt zu einer neuen Klasse von Problemen und führt zu unangenehmen Hacks wie Peer-Abhängigkeiten, die jeder (hoffe ich?) stimmt zu, sind schrecklich. Python möchte wahrscheinlich nicht dorthin gehen (es kann sowieso nicht, da dies wahrscheinlich alle vorhandenen Python-Installationen zerstören würde).

Eine andere Möglichkeit, dies zu umgehen, besteht darin, in den Paketierungstools etwas Cleveres zu tun, das die Abhängigkeitsversion „auflöst“. Bundler (von Ruby) tut dies, indem er den Leuten empfiehlt, die Lock-Datei nicht in das Gem einzubinden, damit Bundler die ungepinnten Versionen in Gemfile anstelle der gepinnten Versionen in Gemfile.lock verwenden kann. Aber die Leute neigen dazu, Ratschläge zu ignorieren und zu tun, was sie wollen, so dass Sie immer noch überall gepinnte Versionen bekommen.

Ich war wohl etwas zu stark um zu sagen, dass es einfach nicht geht . Aber zumindest sind alle bisherigen Versuche gescheitert, und viele von denen, die es versucht haben, sind sehr schlaue Leute, viel klüger als ich. Ich persönlich glaube nicht, dass dies möglich ist, und ich würde weiterhin so denken, bis ich den sehr brillanten Vorschlag sehe, der dies tatsächlich tut.

@tsiq-oliverc Pieter Hintjens schrieb irgendwo ein Konzept von "Kommentare sind willkommen in Form von Pull-Requests"

Ich mag das, weil es den Fokus von philosophischen Ratschlägen auf wirklich greifbare und praktische Dinge verschiebt. Und es begrenzt auch die Anzahl der Kommentare, da ein Kommentator oft auf dem Weg erfährt, dass die Idee im realen Gebrauch unvollständig oder irgendwie kaputt ist.

Ich habe Sie nach einem Beispiel für eine Python-Bibliothek gefragt, in der pipenv ordnungsgemäß verwendet (oder zumindest verwendet) wird und Sie keine bereitgestellt haben.

Sie kommentieren die Qualitäten von tox , geben aber zu, dass Sie damit nicht vertraut sind, und wiederholen immer noch etwas über bewährte Verfahren in der Welt der Python-Paketentwicklung.

Sie sagen, Flask ist möglicherweise ein Sonderfall. Also durchsuchte ich Github nach Python-Projekten mit dem Wort "Bibliothek", sortiert nach der Anzahl der Forks (da es wahrscheinlich widerspiegelt, wie viele Leute damit arbeiten), ignorierte alle "kuratierten Listen von etwas" und zählte die Anzahl der Umgebungen für eine Betriebssystem (normalerweise Linux):

Die tatsächliche Anzahl der Umgebungen, in denen Tests ausgeführt werden sollen, ist meistens 2 (+Windows) oder 3 (+OSX) höher.

tox wird in 2 von 3 Projekten verwendet (ich vergleiche es nicht mit Travis oder Appveyor, da sie eine andere Testebene durchführen).

Die Anzahl der zu testenden Umgebungen ist ziemlich hoch, Flask ist definitiv nicht die wildeste.

Die Anzahl der Umgebungen, für die feste Abhängigkeiten definiert werden müssen, ist wirklich nicht manuell zu verwalten.

Das einfache Ablegen von Pipfile.lock in ein Repository ist ziemlich einfach, aber es bringt keine magische Verbesserung (wenn ja, zeigen Sie mir ein reales Szenario, wann es die Situation verbessern wird).

Vielleicht kennen Sie die goldene Regel aus der "kompilierten" Welt und denken, dass Determinismus (oder Wiederholbarkeit) auch für Python ein Muss ist. Wie Sie sehen, leben wirklich viele Python-Projekte ziemlich gut ohne es, daher kann die goldene Regel hier nicht so streng gelten.

Ich würde mich freuen, wenn wir pipenv für Python-Bibliotheken finden, die die Situation verbessern. Und ich möchte eine Nutzung verhindern, die die Gesamtqualität beeinträchtigen würde.

Um dieses Ziel zu erreichen, gehe ich vor, über Fragen zu iterieren:

  • Soll ich das Tool benutzen?
  • Wie?
  • Warum, welchen Wert habe ich bekommen?
  • Hat es einige Probleme mit sich gebracht? (Mehrarbeit, Fehler werden ausgeblendet...)

@luxus

Sorry, wenn das nicht klar war. Meine lib-Abhängigkeiten sollen das sein, was die Leute derzeit in setup.py / install_requires eingeben. Vielleicht wäre pypi-dependencies ein besserer Name für das, was ich meinte.

Siehe pbr Diskussion in dieser Ausgabe. Es ist das Bestreben, Bibliotheksabhängigkeiten von Pipfile zu unterstützen.

Ich denke, dass ein Pipfile nicht für zwei Zwecke (Lib und App) verwendet werden sollte, diese Dinge müssen separat gemacht werden. Wenn Sie der Meinung sind, dass es wirklich benötigt wird, könnten Sie den Zweck eines Projekts beschreiben, in dem es verwendet wird? Normalerweise versuche ich, Bibliotheksentwicklungs- und Bereitstellungsprojekte getrennt zu halten, da sie im Laufe der Zeit recht unterschiedlich verwendet werden.

@vlcinsky Ich bin mir nicht wirklich sicher, wohin Sie das bringen möchten (ich bin mir nicht sicher, nach welcher Art von PR Sie fragen!), also werde ich mich vorerst aus diesem Gespräch verbeugen.

Um den TL;DR meiner Position neu zu formulieren:

  1. Deterministische Builds sind sehr wünschenswert, an anderer Stelle in der Softwarebranche üblich und mit Pipenv einfach zu realisieren.
  2. Es gibt definitiv einige Randfälle, und jemand sollte dort den Stand der Technik vorantreiben (über Workarounds oder durch bessere Tools).
  3. Es wäre unverantwortlich für die Pipenv-Dokumentation, pauschal von (1) abzuraten, nur weil (2) eine kleine Teilmenge von Fällen betrifft.

@uranusjr Verstanden . Obwohl ich glaube, dass es hier nichts sprachspezifisches gibt, haben sich verschiedene Communities einfach auf unterschiedliche Heuristiken für den Umgang mit einem Problem ohne generische Lösung geeinigt - wenn Sie Versionskonflikte haben, haben Sie ein Problem.

Maven/Java (zum Beispiel) zwingt Sie dazu, zur Build-Zeit darüber nachzudenken. Der NPM-Weg bedeutet, dass Sie Laufzeitprobleme haben, wenn die nicht übereinstimmenden Versionen eine Schnittstelle überschreiten. Laufzeitauflösung (zB Python, dynamische Bibliotheken) bedeutet, dass eine abhängige Datei abstürzen kann/etc. wenn die Abhängigkeitsversion nicht den Erwartungen entspricht.

@vlcinsky

Siehe pbr-Diskussion in dieser Ausgabe. Es ist das Bestreben, Bibliotheksabhängigkeiten von Pipfile zu unterstützen.

pbr scheint nett und alles, aber es fällt in die Kategorie, die ich damit ansprechen wollte:

Ich denke, so etwas würde die Notwendigkeit eines Teils von Anti-Pattern-Abschnitten und Tools von Drittanbietern überflüssig machen, um die Lücke zu füllen.

Ich denke, solche Tools sollten von vornherein nicht notwendig sein.

Wenn Sie der Meinung sind, dass es wirklich benötigt wird, könnten Sie den Zweck eines Projekts beschreiben, in dem es verwendet wird? Normalerweise versuche ich, Bibliotheksentwicklungs- und Bereitstellungsprojekte getrennt zu halten, da sie im Laufe der Zeit recht unterschiedlich verwendet werden.

Wenn es um Pypi-Pakete geht, habe ich Pipenv verwendet, um Entwicklungsabhängigkeiten zu behandeln, Pipfile um Entwicklungsabhängigkeiten zu beschreiben, setup.py um lib-Abhängigkeiten mit install_requires und setuptools in setup.py um mein Paket mit pipenv run python setup.py bdist_wheel upload . Das halte ich für kompliziert.

In anderen modernen Sprachen muss ich ein Befehlszeilentool (Paketmanager) plus ein Abhängigkeitsdateiformat lernen. Die Dokumentation ist an einem Ort und einfacher zu verfolgen und ein Neuling wird all dies in ein paar Stunden klären. Es geht um npm init , npm install foo --dev , npm publish . Pipenv/Pipfile kann das meiste schon, wenn es alles könnte, gäbe es solche Probleme nicht.

Ich wiederhole meine Forderung nach einer Art "Community"-Sektion/Wiki für diese Diskussion. Es gibt mehrere "Muster", die legitim sind, und einige von uns möchten sie vielleicht teilen, "Python-Bibliotheken zu erstellen", einige wie ich mit pbr und andere haben möglicherweise ein sehr gutes Muster. Aber eine Seite im pipenv-Dokument, ich bin mir nicht sicher, ob es eine gute Idee ist.

PS: Um die Migration auf die neue pypi vorzubereiten, sollten Sie twine verwenden und nicht python setup.py hochladen. Die Verwendung von "Upload" sollte als Antimuster betrachtet werden.

Vielleicht kann pipenv "veröffentlichen" Befehle wachsen lassen?

@feluxe Vielleicht möchten Sie einen Blick auf Poesie werfen. Ich stolpere gerade darüber und es scheint, dass es das ist, was Sie suchen.

Es tut, was pipenv tut und mehr und es scheint, dass sie es besser machen, insbesondere in Bezug auf das Abhängigkeitsmanagement (zumindest geben sie so vor). Es übernimmt Abhängigkeitsmanagement, Paketierung und Veröffentlichung eines einzigen Tools poetry .

Ich frage mich, ob pipenv und poetry Anstrengungen unternehmen könnten, um Python endlich einen echten Paketmanager zu geben.

Ich möchte mich noch einmal wiederholen, bevor diese Diskussion zu weit geht. Pipenv kann nicht einfach einen publish Befehl erstellen oder irgendetwas tun, das versucht, die Verpackungsaufgabe zu übernehmen. Dies würde das Ökosystem nur noch mehr fragmentieren, da dies nicht jeder auf diese Weise tut, und da App- und Lib-Abhängigkeiten theoretisch unterschiedlich sind, können Sie niemandem sagen, dass er sie wieder zusammenführen soll, sobald die Unterscheidung in seinem Workflow getroffen wurde.

Es mag den Anschein haben, dass fast jeder an dieser Zusammenführung teilnimmt, aber die Wahrheit ist, dass sich viel mehr Leute nicht an dieser Diskussion beteiligen, weil die Dinge für sie funktionieren und sie etwas anderes tun. Ich habe es wiederholt gesagt: Diskussionen über die Verbesserung des Designs von Toolchains und Dateiformaten sollten an einer höheren Stelle in der Python-Pakethierarchie stattfinden, damit sie mehr Kontakt mit Leuten erhält, die grundlegendere Dinge entwerfen, auf die sich Pipenv stützt. Bitte nehmen Sie die Diskussion dort auf. Es hat keinen Sinn, es hier vorzuschlagen, da Pipenv nicht in der Lage ist, es zu ändern.

Ich habe es wiederholt gesagt: Die Diskussion über die Verbesserung des Designs von Toolchains und Dateiformaten sollte an einer höheren Stelle in der Python-Pakethierarchie stattfinden, damit sie mehr Menschen ausgesetzt ist, die grundlegendere Dinge entwerfen, auf die sich Pipenv stützt.

Ich stimme zu, dass die Diskussion über diesen Fehler jetzt, da das Paketieren und Veröffentlichen auftaucht, außer Kontrolle gerät (dieser Fehler betrifft nur das Abhängigkeitsmanagement!), aber könnten Sie uns bitte an die richtige Stelle für diese Diskussion verweisen? Die Leute haben es hier, weil pipenv als dringend benötigter Schritt in die richtige Richtung angesehen wird, nicht weil sie den pipenv-Maintainern zusätzliche Verantwortung auferlegen wollen.

Edit : Entschuldigung, ich muss den Beitrag verpasst haben, in dem du genau das getan hast, als du die neuen Kommentare zum ersten Mal gelesen hast.

Im Rahmen dieses Vorschlags würde ich jedoch vorschlagen, sich auf die derzeit möglichen Best Practices zu konzentrieren, anstatt in den Kaninchenbau zu gehen, einen neuen Workflow für die gesamte Python-Packaging-Community zu erarbeiten. Es wäre produktiver, innerhalb der aktuellen Einschränkungen eine Best Practice vorzuschlagen und dann die Diskussion über Verbesserungen zu beginnen.

Dem stimme ich sehr zu. Wir sollten zuerst herausfinden , was die beste Workflow für die Bibliothek Maintainer jetzt ist , bevor wir mit großen Plänen kommen. Konzentrieren wir uns also noch einmal darauf, wie wir es am Anfang dieses Threads getan haben. Ich glaube, wir sind noch nicht zu einem Ergebnis gekommen.

Zurück zum Thema: Zitat von @uranusjr , warum Abhängigkeiten in einer anderen Datei für Bibliotheken definiert werden sollten:

Eine andere Möglichkeit, dies zu umgehen, besteht darin, in den Paketierungstools etwas Cleveres zu tun, das die Abhängigkeitsversion „auflöst“. Bundler (von Ruby) tut dies, indem er den Leuten empfiehlt, die Lock-Datei nicht in das Gem einzubinden, damit Bundler die ungepinnten Versionen in Gemfile anstelle der gepinnten Versionen in Gemfile.lock verwenden kann. Aber die Leute neigen dazu, Ratschläge zu ignorieren und zu tun, was sie wollen, so dass Sie immer noch überall gepinnte Versionen bekommen.

Ich war wohl ein bisschen zu stark, um zu sagen, dass es einfach nicht funktionieren wird. Aber zumindest sind alle bisherigen Versuche gescheitert

Ich verstehe immer noch nicht, warum die offizielle Empfehlung für Bibliotheken vorerst nicht sein kann, pipenv für ihre CI-Builds zu verwenden, aber Pipfile.lock außerhalb der Quellcodeverwaltung zu lassen. Da pipenv , wie einige Leute darauf hingewiesen haben, derzeit nichts mit dem Verpackungsprozess zu tun hat, sollten wir nicht auf das oben beschriebene Problem stoßen.

Und ich verstehe auch nicht, warum dies ein Argument gegen die Definition Ihrer abstrakten Abhängigkeiten in derselben Datei ist, die Anwendungen verwenden, um ihre abstrakten Abhängigkeiten zu definieren. Es ist in Ordnung, wenn pipenv keine ausgeklügelte Lösung für die Integration von Pipfile mit setup.py implementieren möchte, aber ich verstehe nicht, warum das im Allgemeinen eine schlechte Idee ist.

@vlcinsky

Ich denke, dass ein Pipfile nicht für zwei Zwecke (Lib und App) verwendet werden sollte, diese Dinge müssen getrennt durchgeführt werden.

Siehe meinen obigen Beitrag. Könnten Sie bitte erläutern, warum Sie das denken? Grundsätzlich kann ich keinen Nachteil erkennen. Im Moment ist es vielleicht eine schlechte Idee, ein Pipfile , da Sie dann die Abhängigkeiten in zwei verschiedenen Dateien auf die gleiche Weise definieren müssen, aber ich habe noch kein Argument gesehen, das erklärt, warum Es wäre eine schlechte Idee, Pipfile für Abhängigkeitsdeklarationen im Allgemeinen zu verwenden.

Beachten Sie, dass ich bereits zugestimmt habe, dass Pipfile.lock nicht in der Quellcodeverwaltung für Bibliotheken sein sollte, es sei denn, Sie befinden sich in der gleichen Situation wie ich.

Bearbeiten : Wenn sich herausstellt, dass pipenv selbst den Unterschied kennen muss, können Sie einfach etwas wie das Feld crate-type cargo einführen, bevor Sie mit der Einführung von app-dependencies und lib-dependencies - das klingt zu kompliziert.

@ Moritz90 Mehrere Mailinglisten von Python wären gute Orte, um diese Diskussion zu führen.

pypa-dev ist am besten umgebende Ökosystem. Ich würde wahrscheinlich hier anfangen, wenn ich eine ähnliche Diskussion posten würde.

python-ideas ist ein Ort, um Ideen zu diskutieren, und hat eine ziemlich hohe Sichtbarkeit für die gesamte Python-Community. Es wäre auch ein guter Ausgangspunkt, wenn Sie dies auf die PEP-Ebene bringen möchten (ich denke, Sie würden es irgendwann tun).

@tsiq-oliverc

Mit PR meine ich: Zeigen Sie ein Beispiel, das Ihr Konzept tragfähig macht.

Also nimm eine vorhandene Bibliothek, fork sie, wende deine (1) an - du sagst, es soll einfach sein mit pipenv und zeig es mir. Ich habe mich ziemlich bemüht und habe Schwierigkeiten.

Wenn Ihr (2) bedeutet, dass „jemand anderes die Arbeit machen muss“, existiert Ihre PR nicht.

In (3) sprechen Sie von einer "kleinen Teilmenge von Fällen", ohne eine reelle Zahl anzugeben. Werden alle Top-Bibliotheken, die ich in Bezug auf die Anzahl der virtuellen Umgebungen beschrieben habe, als "kleine Teilmenge" betrachtet?

Um diese Diskussion abzuschließen, habe ich eine kurze Zusammenfassung der während der Diskussion gefundenen Ergebnisse erstellt.

Fokus: pipenv (Anti-)Muster für Python-Bibliotheken und -Anwendungen

Ich habe den Fokus etwas geändert: Es geht nicht nur um (allgemeine) Python-Bibliotheken, sondern auch um Anwendungen, da es ziemlich billig war, sie einzubinden und die Unterschiede gut demonstrieren.

Ich habe absichtlich alles ausgeschlossen, was Änderungen an bestehenden Tools vorschlägt, wie pipenv , tox usw.

Was ist pipenv und was nicht

  • es ist ein Deployment-Tool, das es ermöglicht, konkrete Abhängigkeiten mit Hilfe von Pipfile.lock zu definieren und anzuwenden.
  • Es ist ein Virtualenv-Management-Tool.
  • Es ist KEIN Paketierungstool im Sinne des Generierens von Python-Paketen.

Bibliotheken und Anwendungen

Das Produkt (Python-Software) ist entweder bereit, in einem anderen Produkt (also einer Bibliothek) verwendet zu werden, oder es ist die endgültige Anwendung, die ausgeführt werden kann.

Persönlich denke ich, dass sogar "Enterprise-Bibliotheken" in die Bibliothekskategorie fallen (es gelten die gleichen Regeln, nur die Anzahl der Ausführungskontexte ist kleiner).

Arten von Softwareprodukten

  • Bibliothek: zur Verwendung in einem anderen Produkt (Bibliothek oder Anwendung)
  • Anwendung: bereitgestellt und ausgeführt werden

Installationsmethoden:

  • Bibliothek: pipenv install <package> also "das Paket ins Spiel bringen (Versionen für andere Bibliotheken auflösen)"
  • Anwendung: pipenv sync also "konkrete Abhängigkeiten anwenden"

Abstrakte und konkrete Abhängigkeiten

Abhängigkeiten von Softwareprodukten

  • abstrakte Abhängigkeiten: müssen verwendete Bibliotheken benennen, dürfen Versionen oder Nutzung einschränken, müssen aber flexibel genug bleiben (dürfen Versionen nicht anheften)
  • konkrete Abhängigkeiten: muss Versionen anheften, idealerweise mit Hashes von verwendeten Bibliotheken

    pipenv Artefakte:

  • Pipfile : abstrakte Abhängigkeiten

  • Pipfile.lock : konkrete (gesperrte) Abhängigkeiten"

Ausführungskontexte

Typische Anzahl verschiedener Ausführungskontexte

  • Bücherei:

    • Python Virtualenvs auf einem Betriebssystem: 3 bis 9 (Tornado mit 30)

    • Anzahl der Betriebssysteme: 1 bis 3 (Linux, OSX, Windows)

    • Gesamtzahl: 3 bis 18

  • Anwendung:

    • Python Virtualenvs auf einem Betriebssystem: 1

    • Anzahl der Betriebssysteme: 1

    • Gesamtzahl: 1 (oder sehr wenige)

CI-Ziele, Prioritäten und Determinismus

CI-Ziel

  • Bücherei:

    • der Code inkl. Seine abstrakten Abhängigkeiten ermöglichen die Installation und die erwartete Funktion innerhalb aller erwarteten Varianten von Ausführungskontexten.

    • Wenn (privat/öffentlich) pypi ein Update der Abhängigkeitsbibliothek erhält, schlägt fehl, wenn dies die getestete Bibliotheksinstallation der Funktion betrifft.

  • Anwendung:

    • Bei der Installation (unter Verwendung konkreter/gepinnter Abhängigkeiten) werden alle erwarteten Funktionen in einem vordefinierten Ausführungskontext bereitgestellt

Besondere CI-Ziele bezüglich Funktionalität:

  • Bücherei:

    • Von der Bibliothek deklarierte abstrakte Abhängigkeiten sind vollständig und enthalten alle notwendigen Einschränkungen (nur bei Bedarf): Bibliothek installiert sich selbst ordnungsgemäß

    • alle erwarteten Anwendungsfälle funktionieren ordnungsgemäß

  • Anwendung:

    • konkrete Abhängigkeiten sind komplett und alle sind gepinnt, am besten inkl. Hashes: Anwendung wird ordnungsgemäß installiert

    • alle erwarteten Anwendungsfälle funktionieren ordnungsgemäß

Verschiedene CI-Testmodi

  • Modus: "Lauf, Wald, Lauf"

    • Die überwiegende Mehrheit der Python-Bibliotheken wird heutzutage auf diese Weise getestet.

    • Verwenden Sie tox oder eine ähnliche Testsoftware

    • Keine Verwendung von pipenv und konkrete Abhängigkeiten (kann für Bibliotheken in Ordnung sein)

  • Modus: "Erzeugen und versiegeln"

    • Keine Pipfile im Repository

    • Pipfile.lock erstellt von pipenv install -e .

    • Pipfile.lock dokumentiert (versiegelt) die Umgebung und ermöglicht die spätere Reproduktion von virtualenv zur Analyse von Problemen.

  • Modus: "Eiszeit"

    • Zweiphasentest

      • Wenn sich abstrakte Abhängigkeiten (definiert innerhalb von setup.py install_requires ) ändern oder das abhängige Paket auf pypi aktualisiert wird, regeneriere Pipfile.lock um pipenv install -e .

    • Funktionstestlauf: Wird ausgeführt, wenn sich der Bibliothekscode ändert. Wird in virtualenv ausgeführt, erstellt von pipenv sync Pipfile.lock

      Wie und von wem kann Pipfile.lock erstellt werden

  • manuell vom Entwickler (kann für Anwendungen funktionieren)

  • automatisch durch CI-Build (und alle Tests bestehen, deklarieren Sie es als verifiziertes Artefakt)

Priorität von Determinismus versus Flexibilität

  • Bibliothek: Flexibilität (wenn möglich ausführen)
  • Anwendung: Determinismus (im ausgewählten Ausführungskontext genauso ausgeführt)

    Was kann den Determinismus des installierten Produkts beeinflussen:

  • public pypi (geringer Determinismus, Pakete werden jederzeit aktualisiert)

  • private pypi (höherer Determinismus, Paketaktualisierungen können kontrolliert werden)
  • abstrakte Anforderungen innerhalb von Bibliotheken (darf nicht für Determinismus verwendet werden)
  • konkrete Anforderungen ( Pipfile.lock ): totaler Determinismus

Sonstig

Einige Anwendungsfälle für Pipfile.lock :

  • (antipattern) Definieren Sie abstrakte Abhängigkeiten der Bibliothek (weil es abstrakt sein muss)
  • (antipattern) Virtualenv für getestete Bibliothek einrichten (kann defekte abstrakte Bibliotheksabhängigkeiten verbergen)
  • Dokumentieren Sie die genaue Virtualenv ("Siegel"), wo ein Test ausgeführt wurde (damit kann der Entwickler es später für fehlerhafte Tests neu erstellen und darin experimentieren)
  • Virtualenv für getestete Anwendung einrichten
  • Anwendung in der Produktion bereitstellen

    Andere Hinweise

  • pbr Bibliothek ermöglicht die Definition abstrakter Bibliotheksabhängigkeiten über requirements.txt . Update-Lesung Pipfile ist unterwegs.

  • poetry Paket versucht etwas Ähnliches wie pyenv

    Häufige Probleme

  • "drop lockfile into repo" und Sie erhalten deterministische Builds:

    • Soll für Bewerbungen funktionieren.
    • Funktioniert nicht für Bibliotheken, da es wirklich zahlreiche Ausführungskontexte gibt und jeder ein gutes Potenzial hat, um zu unterschiedlichen Pipfile.lock . Im Ernst: flask zeigt auf seinen 11 verschiedenen virtuellen Umgebungen (auf einem Betriebssystem) 10 verschiedene gesperrte Abhängigkeiten. Wer wird sie erstellen und verpflichten?
    • Beachten Sie, dass Sie im CI-Modus "Generate and Seal" immer noch Pipfile.lock (aber generiert durch CI-Skript) erhalten können, um die virtuelle Umgebung an anderer Stelle zu regenerieren.
  • Pipfile.lock im Bibliotheks-Repository

    • Wenn es zum Erstellen von virtualenv verwendet wird, kann es fehlerhafte Definitionen von Bibliotheksabhängigkeiten innerhalb von setup.py verbergen.

  • Pipfile im Bibliotheks-Repository

    • wenn es abstrakte Abhängigkeiten wiederholt (die innerhalb von setup.py ), kann es defekte setup.py Abhängigkeitsdeklarationen verbergen.

    • empfohlen: Generieren Sie Pipfile von pipenv install -e . oder pipenv install -e .[tests] wenn Sie auch Testabhängigkeiten benötigen und diese als "Tests"-Extras in den setup.py deklariert sind

  • Hinzufügen von pipenv install <something> zu CI-Skripten

    • es verbessert den Determinismus allein nicht viel

    • siehe "Generate and Seal" CI-Modus (dann müssen alle Installationen in virtualenv über pipenv ).

Schlussfolgerungen

Python-Bibliotheken (insbesondere allgemeine) weisen eine unerwartet hohe Anzahl von Ausführungskontexten auf. Der Grund dafür ist, dass bei Bibliotheken nachgewiesene Flexibilität unter unterschiedlichen Bedingungen das Ziel ist. Die Flexibilität scheint wichtiger als deterministische Builds. Für Leute, die aus der "Compile"-Welt kommen, kann sich dies wie ein sehr schlechtes Antimuster anfühlen. Tatsache ist, dass die meisten (möglicherweise alle) Python-Bibliotheken keine deterministischen Builds bieten (wenn Sie einige kennen, lassen Sie es mich wissen) und Python läuft immer noch sehr gut. Die Gründe, warum Python-Anwendungen noch am Leben sind, könnten sein: Python als Skriptsprache unterscheidet sich von der kompilierten Welt. Der andere Grund könnte sein, dass der Determinismus einen Schritt später aufgelöst werden kann (sollte), sobald eine Anwendung (aus einer Menge von Bibliotheken erstellt) die (natürliche und berechtigte) Forderung nach Determinismus auflösen soll.

Bei Anwendungen ist die Situation genau umgekehrt und hier ist der Determinismus mit Werkzeugen wie pipenv sehr einfach zu erreichen.

Was macht man als nächstes?

  • Ich werde in den nächsten ein, zwei Wochen keine Zeit haben, mich damit zu befassen.
  • Ich kann mir vorstellen, irgendwo eine Reihe von Blogeinträgen zu erstellen (nicht sicher wo). Wenn Sie den Ort kennen (im Idealfall eine Diskussion zulassen), wäre es ein natürlicher Ort, den Inhalt referenzieren, diskutieren und schließlich (wenn er überlebt) irgendwo in Stein gemeißelt werden zu lassen :-).
  • Ich schlage @uranusjr vor , die Kontrolle über dieses Problem zu übernehmen (schließe es, entscheide, was als nächstes zu tun ist, leite die Leute woanders um oder was auch immer praktisch erscheint)

Danke an alle für die sehr anregende Diskussion - ich fühle mich als Botschaft "Ich bin total verloren in diesem Thema" dreimal umgestaltet - was bedeutet natürlich, dass wir besser geworden sind.

@vlcinsky poetry hat nichts mit pyenv zu tun. Es ist ähnlich wie pipenv (aber mit einer viel besseren Implementierung in Bezug auf die Verwaltung von Bibliotheken und Anwendungen, IMO), aber mit dem Paketierungs- und Veröffentlichungsteil.

Sie haben eine pyproject.toml Datei, die Ihr Projekt und seine Abhängigkeiten (abstrakte Abhängigkeiten) definiert, und eine pyproject.lock pyproject.toml Datei, die die angehefteten Abhängigkeiten beschreibt und für jede Python-Version und -Plattform angeheftet ist die pyproject.toml file angegeben hat, um nur eine deterministische Sperrdatei zu haben, um die Probleme zu vermeiden, denen pipenv gegenübersteht. Nur bei der Installation prüft poetry , welche Pakete installiert werden sollen, indem es sie mit der Umgebung abgleicht.

Und wenn es Ihre Bibliothek paketiert, verwendet es die abstrakten Abhängigkeiten (und nicht die angehefteten), damit Sie die Flexibilität bei der Verteilung Ihres Pakets (zum Beispiel über PyPI) behalten.

Dies hat den Vorteil, dass abstrakte Abhängigkeiten für Bibliotheken und die Sperrdatei für Anwendungen verwendet werden. Dies ist das Beste aus beiden Welten.

@zface Poesie, die keine

Im Wesentlichen investieren wir viel Zeit und Mühe in die Belastbarkeit, damit kleine Projekte, die hohe Ansprüche stellen, nicht so viel Aufwand betreiben müssen, weil die Leute nicht auf Grenzfälle stoßen. Wenn Sie wirklich glauben, dass ein anderes Tool Ihnen das Beste aus allen Welten bietet, dann empfehle ich Ihnen, es zu verwenden – pipenv selbst wird in naher Zukunft nicht die Verpackung für Sie übernehmen, wenn überhaupt.

@techalchemy Ich verkaufe wirklich nichts, ich orientiere mich nur an Ideen, die in pipenv verwendet werden könnten.

Und poetry fixiert Abhängigkeiten in pyproject.lock , genau wie pipenv in Pipfile.lock . Sie haben also eine Reproduktion, wie es pipenv bietet. Wenn Sie eine Sperrdatei haben, wird sie verwendet und die angeheftete Abhängigkeit installiert, und wenn ich mich nicht irre, ist es auch das, was pipenv tut.

Abstrakte Abhängigkeiten werden nur verwendet, wenn das Projekt für die Verteilung gepackt wird (also im Grunde genommen für Bibliotheken), da Sie in diesem Fall keine angehefteten Abhängigkeiten möchten.

@vlcinsky Es gibt noch ein paar Punkte, die aussortiert, korrigiert oder erweitert werden müssen, aber ich bin immer noch sehr daran interessiert, dass dies in Dokumentationsform, Pipenv oder anderweitig geht. Haben Sie Interesse, einen Pull-Request einzusenden? Gerne helfe ich bei der Ausarbeitung des Artikels.

Was Poesie angeht, bin ich persönlich kein Fan, aber sie macht viele richtige Dinge. Es sollte wahrscheinlich nicht in Pipenv-Dokumenten erwähnt werden, da es gegen einige Best Practices verstößt, zu denen Pipenv-Entwickler die Leute drängen möchten, aber es sollte erwähnt werden, wenn die Diskussion in pypa-dev oder ähnlichem stattfindet, um ein vollständiges Bild davon zu erhalten, wie die Verpackung ist Ökosystem derzeit ist.

Poesie kann auch mehr Aufmerksamkeit und Beitrag gebrauchen. Dies wäre das Beste für die Community, einschließlich Pipenv. Mit praktikablen Entscheidungen können die Leute ihre Entscheidungen abwägen, anstatt sich kopfüber in Pipenv zu beschweren und sich zu beschweren, dass es nicht das tut, was sie erwarten. Ein guter Wettbewerb zwischen Bibliotheken kann auch technische Verbesserungen im Bereich der Abhängigkeitsauflösung vorantreiben, was Pipenv und Poesie beide tun (und beide nicht perfekt). Wir können viel voneinander lernen.

@uranusjr Ja, ich denke, nur wenige Dinge wurden geklärt und verdienen es, mit einem breiteren Publikum geteilt zu werden. Ihre Hilfe ist wirklich willkommen.

Wie wäre es mit "Paardokumentationserstellung"? Ich denke, dass es im Moment am effektivsten wäre, daran im kleinen Maßstab von nur zwei Personen zu arbeiten.

Denkbar sind (möglicherweise mit ein oder zwei Iterationen):

  • wo genau könnten wir das veröffentlichen
  • Dokumentationselemente (Artikel, Abschnitte) identifizieren
  • Umfang und Ziel jedes Items klären
  • stimme der Gliederung zu
  • offene Probleme identifizieren
  • arbeite sie aus
  • schreibe das Dokument
  • veröffentlichen (und hoffen, dass es angenommen wird)

Wenn Sie Lust haben, es selbst zu schreiben (basierend auf dem, was besprochen wurde) und mich als Rezensenten haben, würde ich mich nicht beschweren.

Ich werde Sie per E-Mail kontaktieren, um die nächsten Maßnahmen zu vereinbaren.

@vlcinsky Ich bin auch als @uranusjr auf PySlackers (einem Slack-Workspace) verfügbar, wenn Sie Echtzeit-Interaktion bevorzugen. Pipenv hat dort einen Kanal ( #pipenv ).

@uranusjr Das meinte ich mit Anstrengung sammeln. Python braucht dringend einen guten Paketmanager wie cargo. Das Python-Ökosystem verblasst im Vergleich zu den anderen Sprachen aufgrund des Fehlens einer Standardmethode. Und pipenv wird da nicht helfen, denke ich.

Was mich stört, ist, dass pipenv selbst als the officially recommended Python packaging tool pipenv bewirbt, obwohl es kein Verpackungstool ist, im Gegenteil, was für die Benutzer irreführend ist. Es ist lediglich ein Abhängigkeitsmanager, der mit einem Virtualenv-Manager gekoppelt ist.

Sie sagen auch, dass es von Cargo, npm, Garn inspiriert wurde, die Verpackungswerkzeuge zusammen mit Abhängigkeitsmanagern sind, während Rohrleitungen dies nicht sind.

Und hier ist der Fehler von pipenv , es trübt nur das Wasser, da die Leute immer noch die gleichen Fehler machen wie zuvor mit requirements.txt vs. setup.py . Projekte werden deshalb immer noch schlecht mit schlecht definierten Abhängigkeiten in ihren setup.py verpackt. Das ist es, was Projekte wie cargo richtig gemacht haben: Sie kümmern sich um alle Aspekte der Entwicklung von Projekten/Anwendungen, um eine Konsistenz zu gewährleisten, während ein Projekt wie pipenv dies nicht tut.

Und wenn du sagst:

was Pipenv und Poesie beide tun (und beide nicht perfekt)

Was meinen Sie? Nach allem, was ich gesehen habe, ist ihr Abhängigkeitsmanager viel widerstandsfähiger als der von pipenv bereitgestellte. Der einzige Nachteil ist, dass sie die PyPI JSON API verwenden, die manchmal aufgrund schlecht veröffentlichter Pakete keine Abhängigkeitsinformationen enthält.

Wie auch immer, ich denke, wie Sie schon sagten, dass beide Projekte voneinander lernen können.

Und noch eine Sache, wie sieht die Zukunft von pipenv aus, wenn pip letztendlich die Pipfile handhabt? Wird es nur ein Virtualenv-Manager sein?

Wenn der Poetry-Abhängigkeitsmanager auf der Json-API basiert, ist dies nicht nur manchmal aufgrund von "schlecht veröffentlichten Paketen" falsch, sondern es wird auch sehr eingeschränkt, was es tatsächlich richtig auflösen kann. Die Warehouse-Json-API veröffentlicht die _aktuellsten_ Abhängigkeiten, auch wenn Sie mit einer alten Version arbeiten, und wenn diese Informationen überhaupt vorhanden sind. Früher haben wir auch die json-API integriert, es war großartig, weil es schnell war, aber das Infrastrukturteam sagte uns, wir sollten ihr nicht vertrauen. Es scheint ein bisschen unaufrichtig, etwas als widerstandsfähig zu bezeichnen, wenn es sich zunächst auf eine unzuverlässige Quelle verlässt.

Letztendlich bestehen die Herausforderungen darin, tatsächlich einen Abhängigkeitsgraphen zu erstellen, der eine Setup-Datei ausführte, da das Paketieren derzeit so funktioniert. Es führt einfach kein Weg daran vorbei. Ein Abhängigkeitsdiagramm, das auf meinem Computer aufgelöst wird, kann sich sogar für dasselbe Paket von einem unterscheiden, das auf Ihrem Computer aufgelöst wird.

Es ist einfach, mit der Hand zu winken und zu sagen: 'Nun, macht das Pipenv nicht einfach zu einem Virtualenv-Manager, wenn pip eine Pip-Datei lesen kann?' Nein. Pipenv ist ein Abhängigkeitsmanager. Es verwaltet idempotente Umgebungen und generiert eine reproduzierbare Lockfile. Mir ist klar, dass Ihnen dies trivial erscheinen muss, weil Sie es wegwinken und dieses Tool auf einen Virtualenv-Manager reduzieren, aber das ist es nicht. Wir lösen Sperrdateien auf und fügen Markierungen für Python-Versionen hinzu, die Sie nicht haben, nicht verwenden, und halten diese verfügbar, damit Sie plattform- und python-Versionen präzise bereitstellen und reproduzieren können. Wir verwenden verschiedene Auflösungsmethoden, einschließlich der Behandlung lokaler Räder und Dateien, vcs-Repositorys (wir lösen dort auch den Graphen auf), Remote-Artefakte, Pypi-Pakete, private Indizes usw.

Am Ende des Tages _will_ pipfiles handhaben, das ist der Plan, der Plan seit der Erstellung des Formats. Aber das ist dasselbe wie die Frage "Aber was ist, wenn pip mit Anforderungsdateien umgehen kann?" Die Frage ist im Grunde identisch. Pip kann dieses Format installieren. Es ist für keine der von mir beschriebenen Funktionen wirklich relevant, außer dass wir die Dateien auch installieren (übrigens mit pip).

@techalchemie

Die Warehouse-Json-API veröffentlicht die neuesten Abhängigkeiten, auch wenn Sie mit einer alten Version arbeiten, und wenn diese Informationen überhaupt vorhanden sind

Das ist einfach falsch, Sie können eine bestimmte Versionsabhängigkeit erhalten, indem Sie https://pypi.org/pypi/{project}/{release}/json aufrufen. Wenn Sie nur https://pypi.org/pypi/{project}/json aufrufen, erhalten Sie sicher nur die letzten Abhängigkeiten, aber Sie können tatsächlich die richtigen Abhängigkeiten erhalten.

Und der Paketierungs-/Publishing-Teil von Python-Projekten muss wirklich verbessert werden, denn am Ende werden alle davon profitieren, da die JSON-API zuverlässig verwendet werden kann.

Es verwaltet idempotente Umgebungen und generiert eine reproduzierbare Lockfile.
Wir lösen Sperrdateien auf und fügen Markierungen für Python-Versionen hinzu, die Sie nicht haben, nicht verwenden, und halten diese verfügbar, damit Sie plattform- und python-Versionen präzise bereitstellen und reproduzieren können.

Und poetry . Und Sie können dafür sorgen, dass die JSON-API nicht verwendet wird, um dieselbe Auflösungsmethode wie pipenv (mit pip-tools) bereitzustellen. Siehe https://github.com/sdispater/poetry/issues/37#issuecomment -379071989 und es wird immer noch widerstandsfähiger sein als pipenv (https://github.com/sdispater/poetry#dependency-resolution )

@zface Ich werde dies ein letztes Mal sagen, bitte bringen Sie dies zu einer höheren Stelle in der Hierarchie. Pipenv erklärt sich nicht selbst als das offiziell empfohlene Python-Paketierungstool; es sagt das, weil es so ist . Wenn Sie das für unangemessen halten, teilen Sie dies den Beamten mit, die Pipenv empfehlen . Bitte legen Sie diese Dinge nicht auf Pipenv dev. Dies ist der falsche Ort, um sich zu beschweren, und Sie können hier unmöglich eine Lösung für Ihre Beschwerden finden. Dort erhalten Sie auch bessere Antworten auf technische Fragen. Dies ist ein Issue-Tracker für Pipenv, kein Diskussionsforum für Python-Paketierungstools und wie Python-Paketierung durchgeführt wird.

Pipenv verlässt sich nicht nur auf pip-tools zur Auflösung, bitte hören Sie auf, unsere Software auf Einzeiler zu reduzieren, die Unverständnis zeigen. Ich weiß sehr gut, wie die PyPI-API funktioniert, ich habe direkt mit dem Team gesprochen, das sie implementiert hat.

Das ist einfach falsch,

Eine solche Haltung ist hier nicht erwünscht. Gehen Sie nicht davon aus, dass wir nicht verstehen, wovon wir sprechen. Bitte üben Sie Höflichkeit.

es wird immer noch widerstandsfähiger sein als pipenv (https://github.com/sdispater/poetry#dependency-resolution)

Pipenv reduziert derzeit keine Abhängigkeitsdiagramme. Es ist töricht, auf ein bestimmtes Problem hinzuweisen, bei dem ein Baum abgeflacht wurde, und zu behaupten, dass das gesamte Werkzeug daher sowohl besser als auch widerstandsfähiger ist. Sie beweisen immer wieder, dass Sie nur hier sind, um Pipenv zu beleidigen und Poesie zu fördern. Bitte machen Sie sich auf den Weg, dieses Verhalten ist nicht erwünscht.

Ich stimme zu, dass die Diskussion weit vom Thema abweicht, da versucht wurde, die "bewährten Praktiken" in der Umgebung von Pipenv zu nutzen.

Jedoch,

[...] werden immer noch die gleichen Fehler wie zuvor mit Requirements.txt vs setup.py machen. Projekte werden deshalb immer noch schlecht mit schlecht definierten Abhängigkeiten in ihrer setup.py verpackt.

Ich teile diese Meinung, neue Entwickler dazu zu bringen, ihren eigenen Python-Code erfolgreich zu paketieren, ist eigentlich komplex, zu komplex, erfordert viel zu viel Online-Dokumentation.
Aber es ist nicht Sache von pipenv oder einer anderen Paketabhängigkeit, damit vollständig umzugehen. Wir konnten die Geschichte nicht umschreiben. Wir als Gemeinschaft müssen einen Weg finden, die Python-Toolkette Schritt für Schritt zu modernisieren.

Und Pipenv (und wahrscheinlich Poesie) ist ein sehr guter Schritt nach vorne.

Auf der einen Seite Pipfile für die Anwendung und setup.py für Bibliotheken auf der anderen Seite pflegen zu müssen, ist ein Kinderspiel. Egal wie schwer wir es mit vielen Worten, langen Artikeln und Good-Practice-Leitfäden erklären, es ist zu komplex für das, was es ist. Ich stimme voll und ganz zu, dass es im Moment so ist, aber es sollte uns nicht daran hindern, uns einen besseren und sichereren Weg vorzustellen.
Am Ende möchte ich als Entwickler ein einziges Tool, vielleicht mit zwei verschiedenen Modi, das mir hilft und mein Leben so einfach wie möglich macht.

Sie sollten eine Möglichkeit sein, nur den Teil zu extrahieren, der requirements.txt/Pipfile aus Libs wie PBR macht, um eine Art 'easy setup.py' vorzuschlagen, einen Pipfile-fähigen Wrapper um install_requires , ohne all das unerwünschte Verhalten, das pbr mit sich bringt, und packe das in einen dedizierten setuptools-Wrapper, der nur das tut.

So könnten wir das Beste aus jeder Welt haben:

  • pipenv zur Pflege von Pipfile (in Bibliotheken und Anwendungen versioniert)
  • pipenv zur Pflege von Pipfile.lock (nur für Anwendungen versioniert)
  • man würde dieses magische Wrapper-Paket ( pipfile_setuptools , install_requires_pipfile ?) verwenden, das eine Abhängigkeit der ersten Ebene wäre, deren Aufgabe nur darin besteht, Pipfile in install_requires .

Dies ist ein weiteres Projekt, das nicht mit pipenv , aber dennoch eine generische Pipfile Parserbibliothek benötigt. Was denken Sie?

@gsemet Nach meinem Verständnis hat PyPA versucht, dies stattdessen mit pyproject.toml zu füllen, angeführt von flit . Sie müssen zuerst mit ihnen (bei pypa-dev oder distutils-sig) darüber sprechen, bevor Sie Pipfile als Quellformat verwenden. Was das Parsen von Pipfile (und der Sperrdatei) angeht , wird dies in


Bearbeiten: Bitte senden Sie mir eine Nachricht, wenn Sie sich entscheiden, eine Diskussion darüber in einer der Mailinglisten zu beginnen. Ich habe einige Ideen, wie wir die beiden Teile der Python-Paketverteilung zusammenbringen können.

Ich muss zugeben, dass ich ein bisschen traurig bin, Abhängigkeiten zu sehen, die in pyproject.toml deklariert sind (was die Rollen wie setup.cfg von PBR übernimmt), während PyPa auch Pipfile ....

Danke für den Hinweis auf Flit und Pipfile. Es gibt auch die Pipenvlib von Kennethreitz , die leichter erscheint.

Die setup.cfg von PBR scheint im Vergleich zur offiziellen Dokumentation vollständiger zu sein (z. B.: data_files ) und die Wiederverwendung einer Datei, die bereits mit mehreren Tools (flake8, pytest, ...) geteilt wurde, kann dieselbe Datei verwenden, wodurch die Anzahl der Datei im Stammverzeichnis eines Python-Projekts)

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen