Ich öffne dieses Thema als Versuch, die Diskussion über Out-of-Tree-Builds, die damit verbundenen Probleme und mögliche Lösungen zu konsolidieren.
Welches Problem wird diese Funktion lösen?
Wenn Sie Projekte aus lokalen Verzeichnissen erstellen, kopiert pip diese zuerst
Dieser Ansatz hat im Laufe der Zeit eine Reihe von Problemen aufgeworfen:
Warum kopiert pip vor dem Erstellen in ein temporäres Verzeichnis? Vorbehalt: Das ist mir unklar - das habe ich bisher gesammelt:
Mögliche Lösungen
Zusätzlicher Kontext
Weitere Diskussionen zum Bauen über sdist auf Discussion.python.org .
Betrachtet man dies aus der Perspektive des Backends, ist die Idee eines "Out-of-Tree-Builds" eigentlich bedeutungslos. Das Backend erhält einen "Quellbaum" in Form des aktuellen Verzeichnisses des Prozesses und wird aufgefordert, einen Build auszuführen. Es hat keine Möglichkeit zu wissen, ob dieses Verzeichnis aus einem sdist extrahiert, aus einem VCS ausgecheckt oder von woanders kopiert wurde. Alles, was es tun kann, ist zu bauen, und wenn es nicht über das verfügt, was es zum Erstellen benötigt, melden Sie Fehler.
Das tötet die mögliche Lösung (3) IMO - das Backend hat kein Konzept dafür, was ein In-Place-Build ist , daher kann es nicht sagen, ob ein solcher Build sicher ist 1 .
Was (2) angeht, bin ich generell gegen zusätzliche Optionen wie diese. Wenn wir wissen, was am besten zu tun ist, sollten wir es tun, und wenn nicht, dann ist die Weitergabe des Problems an den Benutzer keine besonders freundliche Option. Das Problem hier ist subtil genug, dass ich erwarten würde, dass nur wenige Benutzer wissen, was die richtige Wahl ist, daher würden wir wahrscheinlich sehen, dass Leute nur die beiden Optionen ausprobieren und blindlings "was auch immer funktioniert" verwenden. Außerdem sind die Auswirkungen auf den Support erheblich. Das Anbieten einer Option bedeutet eindeutig, dass wir zumindest in einigen Fällen davon ausgehen, dass die Build-Ergebnisse unterschiedlich sind. Wie können wir also testen, ob die Unterschiede unseren Erwartungen entsprechen? Sind wir dafür verantwortlich, Benutzer darüber aufzuklären, wann das Flag für den In-Place-Build benötigt wird oder nicht (entweder über unsere Dokumentation oder aufgrund von Problemen, die von Benutzern angesprochen werden, die nicht wissen, welche sie verwenden sollen)?
Trotzdem bin ich nicht dagegen, dass Pip einfach an Ort und Stelle baut. Ich glaube, der Grund, warum wir das nicht tun, ist, dass wir Fälle hatten, in denen Artefakte, die von einem vorherigen Build übrig geblieben sind, in einem nachfolgenden Build verwendet wurden, aber mit anderen Optionen erstellt wurden (z vom gleichen Baum). Es ist jedoch vernünftig zu sagen, dass Backends sicherstellen sollten, dass solche Probleme nicht auftreten. Ich bin mir jedoch nicht sicher, ob eine solche Haltung besonders benutzerfreundlich ist - dies kam während der PEP 517-Diskussionen zum Thema inkrementelle Builds auf und war so umstritten, dass es damals verschoben wurde.
Meine Vorliebe war es, seit langem ein sdist zu bauen und dann das Rad daraus zu bauen (Ihre Option 1). Ich bin mit dem Pip-Building einverstanden (wenn wir uns darauf einigen können, dass dies sicher ist, da wir, wie oben erwähnt, nicht erwarten können, dass das Back-End uns dies mitteilt), aber ich denke, das würde eine Community brauchen Diskussion, um die weiteren Auswirkungen (auf Backends, Pip/Frontends und Endbenutzer) auszuloten.
1 Es wäre natürlich möglich, PEP 517 zu aktualisieren, um zu festzulegen .
Ich habe die Lösungen 4. (Ändern Sie pip so, dass es immer an Ort und Stelle erstellt wird) und 5. (Ändern Sie pip so, dass es standardmäßig mit einer Option zum Erstellen außerhalb des Baums erstellt wird).
Ich habe gemischte Gefühle beim Bauen über sdist (Lösung 1.) aus folgenden Gründen:
UnsupportedOperation
für build_sdist
zu erhöhen.Dieser Beitrag zum Thema "Diskussieren" fasst auch ähnliche Argumente zusammen.
Ich stimme zu, dass der Weg für Lösung 3 alles andere als offensichtlich ist.
Ich stimme auch zu, dass wir zusätzliche Optionen vermeiden sollten, wenn wir können.
Ich stelle auch fest, dass es im verlinkten Diskussionsthread einige Stimmen für In-Place-Builds gab, aber in der Tat ist eine fokussierte Community-Diskussion zu diesem speziellen Thema erforderlich, wenn wir diesen Ansatz untersuchen möchten.
- Bauen Sie ein sdist an Ort und Stelle, entpacken Sie das sdist an einem temporären Ort und bauen Sie dann daraus.
Ich denke, das ist ein guter Ansatz.
IMO-Chancen stehen gut, dass dies für ein einzelnes Paket in den meisten pip install
-Ausführungen mit lokalen Verzeichnissen ausgeführt wird - am häufigsten stelle ich mir pip install .
. Dies würde wahrscheinlich als Teil des Paketentwicklungsworkflows erfolgen.
Ich denke, dieses Verhalten sollte wie folgt aussehen:
Wenn wir local-dir -> sdist -> wheel ausführen, haben wir einen zusätzlichen Satz von Aufrufen. Ich denke jedoch, dass es vernünftig ist, zu überprüfen, ob generierte sdists vernünftig sind, insbesondere während der Entwicklung. tox macht dies bereits als Teil seines Workflows, Check-Manifest, um die nicht so benutzerfreundlichen Schnittstellen von setuptools hier abzudecken.
Insgesamt denke ich, dass sich die Kosten für die Erstellung eines sdist bei einem lokalen Verzeichnis lohnen, um solche Fehler in Projekten zu vermeiden, insbesondere da Leute, die aus lokalen Verzeichnissen installieren, wahrscheinlich die Entwickler des Projekts selbst sind.
Was den Rollout angeht, sollten wir abwarten und beobachten, wie #6536 auf den Markt kommt. Wir würden auf jeden Fall ein paar Dinge lernen, die übertragen werden können.
Ich ziehe den Bau / ohne Sdist an Ort und Stelle zu installieren (so setup.py install
oder setup.py bdist_wheel
oder Aufruf build_wheel
als anwendbar auf dem PEP 517 Back - End) vs einem Sdist Aufbau, Auspacken und Installieren davon. Meine konkreten Gründe sind:
setup.py install
). Benutzer, die von local-dir -> installiert gehen möchten, können pip install local-dir
ausführen. Benutzer, die von local-dir -> sdist -> installiert gehen möchten, können ein sdist erstellen und dann pip install ./path/to/sdist
ausführen. Es gibt viele alternative Tools, die einen sdist erstellen können, und dies ist etwas, das Benutzer wahrscheinlich bereits haben werden, es sei denn, sie erstellen die Distributionen, die sie auf PyPI hochladen, von Hand.pip install local-dir
ausführen. Die Benutzer ohne Optionen fragen pip nach Optionen zur Steuerung des Verhaltens oder müssen ein anderes Tool finden, das sie sonst nicht benötigt hätten.Unabhängig von der Herangehensweise ist das einzige Problem, das ich bei der Durchführung von Dingen an Ort und Stelle sehe, dass wir bei Setuptools-Builds (ich denke, dies gilt für Legacy und PEP 517) am Ende .egg-info
im Projektverzeichnis landen, was falsch wird als "installiertes Paket", wenn pip mit python -m pip
in diesem Verzeichnis aufgerufen wird. Dies würde durch #4575 behoben, das das aktuelle Verzeichnis vermutlich NICHT in die Abfrage nach installierten Paketen für jedes Schema einbeziehen würde.
Ich habe festgestellt, dass ich zustimme, dass die Idee, den sdist-Build zu überspringen und direkt einen In-Tree-Build durchzuführen, ein besserer Ansatz für pip ist, um standardmäßig zu gehen, und nicht zu versuchen, local-dir -> sdist -> wheel zu tun.
Wenn wir in Fedora Python-RPM-Pakete erstellen, sind wir Dinosaurier und der Standardweg ist die Verwendung von python setup.py build
. Mit PEP 517 haben wir stattdessen eine "vorläufige" Möglichkeit hinzugefügt, pip wheel
verwenden. Bei Erweiterungsmodulen haben wir jedoch ein Problem mit dem Ansatz "Quellen nach tmp verschieben, von dort erstellen", den pip verwendet, um sie zu erstellen.
Unsere Build-Maschinerie fügt einige Compiler-Flags ein, sodass die Build-Artefakte (in diesem Fall .so
Erweiterungsmodule) Metadaten über ihre Quellen enthalten. Später gibt es ein Shell-Skript, das die Build-Artefakte durchläuft, diese Informationen extrahiert und die Quellen nach /usr/src/debug
kopiert, um sie über ein spezielles *-debugsource
RPM zu installieren. Die Maschine erwartet, dass alles innerhalb des Arbeitsbaums gebaut wird und es funktioniert nicht wirklich gut, wenn es draußen gebaut wird. Hier sind die Dinge, die (gemeinsam) getan werden können, um das Problem auf unserer Seite zu mildern:
$TMPDIR
, dass sie sich an der Stelle befindet, an der das RPM-Skript sie erwartet (dh export TMPDIR=%{_builddir}/.tmp
(und erstellen))pip wheel
mit der Option --no-clean
, um die kopierten Quellen in $TMPDIR
zu behaltenfind %{buildroot} -iname '*.so' -print0 | xargs --no-run-if-empty -0 -n1 /usr/lib/rpm/debugedit -b "%{_builddir}/.tmp/pip-req-build-"* -d "$PWD"
$TMPDIR
manuell reinigen.)Der dritte Schritt gefällt uns nicht besonders, da er auf zu vielen Implementierungsdetails angewiesen ist:
/usr/lib/rpm/debugedit
API und Standort (und Existenz)pip-req-build
NameWenn pip immer an Ort und Stelle gebaut würde oder wenn es dafür einen Befehlszeilenschalter gäbe, würde das Problem verschwinden.
Downstream-Bericht: https://bugzilla.redhat.com/show_bug.cgi?id=1806625
Ich habe festgestellt, dass ich zustimme, dass die Idee, den sdist-Build zu überspringen und direkt einen In-Tree-Build durchzuführen, ein besserer Ansatz für pip ist, um standardmäßig zu gehen, und nicht zu versuchen, local-dir -> sdist -> wheel zu tun.
Ich neige auch immer mehr dazu, die Idee eines In-Place-Radbaus zu akzeptieren. Meine restlichen Reservierungen sind:
... und natürlich muss jemand eine PR schreiben, die diese Änderung implementiert (mit Tests, Dokumenten usw. - das Übliche) sonst reden wir nur
Wir würden uns darauf verlassen, dass sich das Backend "richtig" verhält - zB keine anderen Ergebnisse basierend auf übriggebliebenen Daten aus früheren Builds oder was auch immer liefert. Ich bin mit dieser Annahme einverstanden, aber ich mache mir Sorgen über die Supportkosten, wenn wir anfangen, Leute dazu zu bringen, zu sagen "Pip hat mein Rad falsch gebaut" und wir müssen nur debuggen, um festzustellen, dass es sich um ein Backend-Problem handelt.
Wäre es sinnvoll, die PEP 517-Schnittstelle um einen „sauberen“ Hook zu erweitern? Wir würden es wahrscheinlich sowieso irgendwann wollen, um andere Bemühungen zu ermöglichen (zB bearbeitbare Installation implementieren, ein Paketentwicklungstool erstellen, das jedes PEP 517-Projekt erstellt). pip kann es hier aufrufen, um sicherzustellen, dass kein Junk übrig ist, bevor der Build im Baum ausgeführt wird.
Wäre es sinnvoll, die PEP 517-Schnittstelle um einen „sauberen“ Hook zu erweitern?
Vielleicht? Aber wenn pip automatisch clean
aufruft, gibt es bestimmt jemanden, der dies nicht möchte, inkrementelle Builds oder so. Und dann haben wir am Ende eine andere Option.
Meine Neigung ist, bei meiner Position zu bleiben: "Wir müssen in der Lage sein, davon auszugehen, dass es in der Verantwortung des Backends liegt, sicherzustellen, dass In-Place-Builds korrekt funktionieren". Selbst wenn sich das als unhaltbar herausstellt, helfen uns konkrete Beispiele dafür, warum es nicht funktioniert, besser zu verstehen, was wir mit dem Problem tun können, anstatt nur zu raten.
- Wir würden uns darauf verlassen, dass sich das Backend "richtig" verhält - zB keine anderen Ergebnisse basierend auf übriggebliebenen Daten aus früheren Builds oder was auch immer liefert.
Ich wäre versucht, PEP-517 zu erweitern, um dies zu einer expliziten Anforderung zu machen.
Ich wäre versucht, PEP-517 zu erweitern, um dies zu einer expliziten Anforderung zu machen.
Das sagt es schon:
Das Back-End kann Zwischenartefakte in Cache-Speicherorten oder temporären Verzeichnissen speichern. Das Vorhandensein oder Fehlen von Caches sollte keinen wesentlichen Einfluss auf das Endergebnis des Builds haben.
Es ist nicht so sehr wahrscheinlich, dass Backends diese Anforderung absichtlich verletzen, da Benutzer das Problem natürlich als Pip-Problem melden und zum Backend-Projekt weitergeleitet werden, was ein bisschen zusätzlicher Aufwand ist.
Beim Versuch, eine Problemumgehung für Fedora zu finden, wurden wir von https://github.com/pypa/pip/issues/7872 getroffen
Da wir das Problem ".egg-info in cwd" mit #7731 und Freunden behoben haben, ist dies eine Sache weniger, um die Sie sich beim Bauen Sorgen machen müssen.
Also wurde Option 4 (immer eingebaut) in #7882 implementiert.
Wir haben jetzt (gemäß #7951) eine Betaversion von pip veröffentlicht, pip 20.1b1. Diese Version enthält #7882, die eine Lösung für dieses Problem implementiert hat.
Ich hoffe, dass die Teilnehmer dieser Ausgabe uns helfen werden, indem sie die Beta testen und nach neuen Fehlern suchen. Wir möchten mögliche Probleme vor dem Hauptrelease 20.1 am Dienstag identifizieren und beheben.
Ich freue mich auch über positive Rückmeldungen nach dem Motto "yay, es funktioniert jetzt besser!" auch, da der Issue Tracker normalerweise voller "Probleme" ist. :)
Wir planen total, es in Fedora zu testen (wir haben das bereits vor Ihrem Kommentar geplant), aber die Frist für Dienstag ist wahrscheinlich nicht realistisch.
@hroncok Irgendeine Idee, bis Fedora diese Änderungen testen kann?
Ich werde versuchen, es am Montag irgendwie zu schaffen, kann aber keine Versprechungen machen.
Tatsächlich lässt 20.1b1 unsere Probleme verschwinden.
Allgemeineres 20.1b1-Feedback in https://mail.python.org/archives/list/[email protected]/message/5EAUIYYIRKXEHTAG5GQ7EJHSXGZIW2F7/
Hurra! Vielen Dank für das Ausprobieren der Beta @hroncok! Sehr geschätzt! ^>^
Ein Ergebnis von Build-in-Place: Ich hatte parallel Räder für mehrere Python-Versionen gebaut (in einem Manylinux-Docker-Container). Bei In-Place-Builds funktionieren parallele Builds nicht, da die verschiedenen Versionen in Konflikt geraten. Bei Out-of-Tree-Builds erstellte jede Version einen separaten Baum und hatte kein Problem.
@manthey diese Diskussion ist unter #8168
Es ist also mehr als 10 Tage her. Es wurden einige Probleme bezüglich der Änderung angesprochen (alles erwartet, würde ich sagen - #8165, #8168, #8196). Es gab auch Leute, die ausdrücklich erwähnten, dass die Veränderung ihnen hilft.
bdist_wheel
--bdist-dir
, schreibt aber immer noch .egg-info
in siehe auch https://github.com/pypa/setuptools/issues/1816, https://github.com/pypa/setuptools/issues/1825). Nun, da sich pip korrekt verhält, kann sich die Diskussion vielleicht verschieben, um zu sehen, ob zB setuptools eine Option entwickeln kann, um einen Build durchzuführen, ohne das Quellverzeichnis zu berühren, und dann zu prüfen, ob eine PEP 517-Änderung erforderlich ist oder diese Option nicht steuert.Ich hasse es also, Änderungen zu durchbrechen, aber dieser wurde nicht leichtfertig gemacht, und aus diesen Gründen neige ich persönlich dazu, ihn beizubehalten.
Ich stimme nicht zu, dass sich das neue Verhalten "richtig", sicher anders verhält und anscheinend in einigen Fällen anders gebrochen ist, und ich denke, es ist falsch, es als solches zu formulieren. Es stellt einen Kompromiss für eine Gruppe von kaputten Benutzern für eine andere Gruppe dar. In beiden Fällen gab es hier Abhilfen, die durchgeführt werden konnten.
Ich hätte diese Änderung nicht zusammengeführt und hätte sie verpasst, oder ich hätte dagegen argumentiert (und ich denke, dass es jetzt, nachdem sie zusammengeführt wurde, es einigen macht, pip als Zwangsfunktion zu verwenden, um zu helfen, bestimmte Arten von kaputten Paketen zu verhindern, erheblich schwieriger ). Davon abgesehen weiß ich nicht wirklich, ob hier ein Zurücksetzen das Richtige ist. Es kann für Benutzer noch verwirrender werden, wenn das Verhalten viel herumläuft. Wenn wir umkehren, sollten wir es schnell tun, wenn nicht, sollte das aktuelle Verhalten wahrscheinlich für besser oder schlechter stehen.
Ich habe den Begriff "richtig" verwendet, denn bevor pip wheel <localdir>
und pip install <localdir>
cd <localdir> ; setup.py bdist_wheel
in einigen Fällen ein anderes Rad als https://github.com/pypa/pip/issues/7555#issuecomment -595180864 oder #6276 oder einfache Fehler. Ich glaube nicht, dass pip 20.1 so schlechte Räder/Installationen erzeugt, daher glaube ich, dass es in diesem Sinne tatsächlich richtiger ist.
Natürlich wussten wir, dass die Änderung einige Arbeitsabläufe unterbrechen würde, und der Kompromiss muss jetzt, da wir Feedback haben, neu bewertet und rückgängig gemacht oder endgültig bestätigt werden.
Und es kann immer noch andere Räder als setup.py sdist && pip install dist/*.tar.gz
.
Mein Vorschlag wäre, den PR rückgängig zu machen und den Fix zu implementieren, indem man zuerst einen sdist durchmischt und dann ein Rad aus dem resultierenden sdist baut.
Dies sollte alle Korrektheitsprobleme lösen, außer in Fällen, in denen das Projekt nicht in der Lage ist, ein sdist korrekt zu erstellen, und das ist IMO kein wichtiger Anwendungsfall, für den es zu lösen ist.
Der Kompromiss dort ist, dass es langsamer sein wird. Sobald wir dies jedoch implementiert haben, können wir die PEP 517-Schnittstelle weiter verfeinern, um optionale APIs hinzuzufügen, die eine Beschleunigung ermöglichen. Das wird wahrscheinlich noch nie so schnell gehen wie diese Änderung, aber wir können dem sicherlich näher kommen.
Diese Änderung macht es praktisch unmöglich, die Genauigkeit weiter zu erhöhen, ohne Leistungsregressionen einzuführen, über die Benutzer wahrscheinlich nicht glücklich sein werden. Wenn wir es jedoch richtig machen und dann mit der Leistung verbessern, können wir einen glücklichen Mittelweg finden, der beide Seiten zufrieden stellt.
Wie das alte Sprichwort sagt, machen Sie es zuerst richtig, dann schnell. Ich fürchte, mit dieser PR haben wir es schnell geschafft und unsere Fähigkeit, es richtig zu machen, ausgesperrt.
Ich stimme immer noch zu, dass die Validierung von sdists wünschenswert ist, jedoch nicht zum Zeitpunkt der Pip-Installation. Vielleicht ist dies eine Funktion für ein zukünftiges sdist-Builder-Tool oder einen Pip-Build-Befehl.
Außerdem erstellt setup.py sdist
.egg-info im lokalen Verzeichnis, sodass die gemeldeten Probleme mit schreibgeschützten Quellverzeichnissen oder gleichzeitigen Builds bestehen bleiben.
Wenn dies nicht zur Pip-Installationszeit geschieht, geschieht dies funktional erst zur Pip-Installationszeit einer anderen Person. Das Überspringen bedeutet nur, dass wir mehrere Pfade haben, die ein Projekt von VCS zum installierten Paket fortsetzen kann, und jeder Pfad ist eine weitere Chance für Unterschiede. Dies ist keine neue Sache, im Grunde hat jede Option, die den Installationspfad ändert, selbst bei den anspruchsvollsten Projekten einen anderen Satz von Bytes auf der Festplatte. Es gibt immer subtile Unterschiede, und Sie hoffen nur, dass diese Unterschiede keine Bedeutung haben – oder Sie können alles tun, um diese Unterschiede zu beseitigen, indem Sie es strukturell unmöglich machen, sie von Anfang an zu haben.
Einige Leistungsprobleme könnten tatsächlich wieder auftreten, wenn/beim Erstellen über sdist, aber sie wären wahrscheinlich eine Größenordnung niedriger als das, was wir in pip < 20.1 hatten. Tatsächlich entstand das meiste davon, dass man .git
oder ein venv
kopierte, oder andere unzusammenhängende umfangreiche Sachen, die nicht im sdist enthalten wären.
Unabhängig davon, womit pip
letztendlich enden wird, könnten wir die andere Option wählen, da es unwahrscheinlich ist, dass eine von beiden in der Lage ist, alle zufrieden zu stellen? Ich kann mir vorstellen, dass, wenn der aktuelle Ansatz beibehalten werden soll (ich habe nicht wirklich eine Meinung dazu, was der Standard sein sollte), wir in der Lage sein sollten, einen Fallback für das letzte Ergebnis bereitzustellen, bei dem ein Benutzer wählen kann, einen sdist zu erstellen und zu installieren das Paket von dort.
Außerdem erstellt
setup.py sdist
.egg-info
im lokalen Verzeichnis, sodass die gemeldeten Probleme mit schreibgeschützten Quellverzeichnissen oder gleichzeitigen Builds bestehen bleiben.
Ich denke (zumindest ein kurzer Test stimmt mir zu), dass nur setuptools
(nicht distutils
) dies tut, und dieses Verhalten ist konfigurierbar, um das Verzeichnis woanders zu erstellen. Ähnlich wie bei anderen Backends sollten wir ihnen empfehlen können, eine saubere sdist-Generierung durchzuführen.
FWIW, ich glaube nicht, dass wir das sdist-generation --egg-info
Verzeichnis in das Arbeitsverzeichnis ablegen müssen, wenn wir den Ansatz von generate-sdist-unpack-it-build-wheel verwenden, da wir es können Legen Sie das in ein temporäres Verzeichnis ab, wie wir es für generate_metadata
tun.
@pradyunsg erfordert das keine Änderung der Setuptools? Als ich das letzte Mal den sdist
Befehl überprüft habe, hatte ich keine Option zum Angeben des .egg-info
Basisstandorts, im Gegensatz zu egg_info
das eine --egg-base
Option hat, die wir genutzt haben in #7978.
In der Tat! Ich habe in den Setuptools nach der falschen Datei gesucht. 🙈 Ich stehe korrigiert.
Warum ist in diesem Raum alles so komplex? :(
$ ls -la
total 8
drwxr-xr-x 3 dstufft staff 96 May 6 14:26 .
drwxr-xr-x 9 dstufft staff 288 Apr 28 15:46 ..
-rw-r--r-- 1 dstufft staff 85 Apr 23 16:23 setup.py
$ py setup.py egg_info --egg-base /tmp/foo sdist
/Users/dstufft/.pyenv/versions/3.8.2/lib/python3.8/site-packages/setuptools/dist.py:471: UserWarning: Normalizing '2020.04.23.3' to '2020.4.23.3'
warnings.warn(
running egg_info
creating /tmp/foo/dstufft.testpkg.egg-info
writing /tmp/foo/dstufft.testpkg.egg-info/PKG-INFO
writing dependency_links to /tmp/foo/dstufft.testpkg.egg-info/dependency_links.txt
writing top-level names to /tmp/foo/dstufft.testpkg.egg-info/top_level.txt
writing manifest file '/tmp/foo/dstufft.testpkg.egg-info/SOURCES.txt'
reading manifest file '/tmp/foo/dstufft.testpkg.egg-info/SOURCES.txt'
writing manifest file '/tmp/foo/dstufft.testpkg.egg-info/SOURCES.txt'
running sdist
warning: sdist: standard file not found: should have one of README, README.rst, README.txt, README.md
running check
warning: Check: missing required meta-data: url
warning: Check: missing meta-data: either (author and author_email) or (maintainer and maintainer_email) must be supplied
creating dstufft.testpkg-2020.4.23.3
copying files to dstufft.testpkg-2020.4.23.3...
copying setup.py -> dstufft.testpkg-2020.4.23.3
Writing dstufft.testpkg-2020.4.23.3/setup.cfg
creating dist
Creating tar archive
removing 'dstufft.testpkg-2020.4.23.3' (and everything under it)
$ ls -la
total 8
drwxr-xr-x 4 dstufft staff 128 May 6 14:28 .
drwxr-xr-x 9 dstufft staff 288 Apr 28 15:46 ..
drwxr-xr-x 3 dstufft staff 96 May 6 14:28 dist
-rw-r--r-- 1 dstufft staff 85 Apr 23 16:23 setup.py
https://github.com/pypa/pip/issues/8165#issuecomment -624669107 das fühlt sich an wie eine hübsche Show, die den Fehler stoppt, wohl nicht unser Fehler, aber es ist eine Art von Fehlern, die meiner Meinung nach während der PEP 517-Diskussion auftreten würden, wenn Das Ausführen von In-Place-Builds wurde standardmäßig angezeigt.
bdist_wheel
wurde in der Vergangenheit gebeten, sein Build-Verzeichnis automatisch zu bereinigen. Diese Funktion sollte eingebaut werden. Sind die anderen distutils-Builds sauber?
Wenn es sich um SCons handelte, würde es sich an die Dateien erinnern, die ihm wichtig waren, und zusätzliche Dateien im build/-Verzeichnis vom Rad weglassen, selbst wenn sie im Dateisystem vorhanden waren.
Ich glaube, das obige Problem betrifft nicht nur Manylinux. Dies sollte immer dann passieren, wenn das Build-Verzeichnis nicht spezifisch genug ist, um das ABI zu erfassen (im Fall von setuptools scheint es, dass nur die Plattform und die Python-Version im ABI-Tag im Build-Verzeichnis erfasst werden). Ich denke, dies geht auch mit dem aktuellen Interpreter über ABI hinaus. Wenn zum Beispiel etwas gegen NumPy verlinkt, denke ich, dass es ein ABI hat, das auf neueren, aber nicht auf älteren NumPy funktioniert, und es sei denn, sie codieren dies in der Benennung des Build-Verzeichnisses, dann wird dies Effekt verwendet auch so.
Das automatische Bereinigen des Build-Verzeichnisses löst das Problem nicht, es macht es nur weniger wahrscheinlich (zum Beispiel könnte das parallele Ausführen von zwei pip wheel
Aufrufen immer noch das Problem auslösen), obendrein einer der vermeintlichen Gründe für die Implementierung Auf diese Weise (zumindest während der PEP 517-Diskussion) würde dies mehr Leistung bieten, indem das Caching zwischen Aufrufen für inkrementelle Builds ermöglicht wird. IOW das aktuelle Verhalten ist das, was eine Teilmenge wollte, die Wiederverwendung von Build-Artefakten zwischen den Durchläufen Paketanpassung).
Mit genügend Flags für den zugrunde liegenden setuptools
Befehl können Sie dies natürlich beheben (etwas wie py setup.py egg_info --egg-base /tmp/foo build --build-base /tmp/foo/build-base bdist_wheel --bdist-dir /tmp/foo/bdist
würde es tun).
Ich möchte jedoch wiederholen, dass das Problem nicht an zusätzlichen Dateien liegt, sondern daran, dass die erwartete ABI, mit der das Rad kompatibel war, geändert wurde und die .so
nicht neu erstellt wurden. Wenn SCons schlau genug ist, um zu wissen, dass Python, das mit pymalloc erstellt wurde, ein Build-Verzeichnis benötigt und Python mit einem anderen erstellt wird (einschließlich Dinge wie NumPy-Versionen, auf die .so
möglicherweise verlinkt), dann ist es nicht betroffen. Wenn es ein zuvor erstelltes Artefakt mit einer anderen ABI wiederverwenden würde, ist es betroffen.
Ich habe versucht, Enscons zu testen, aber ich konnte rsalette nicht ohne Fehler erstellen.
Ich habe versucht , zu Test scikit-build zu sehen , wie es behandelt inkrementelle baut, und egal , was ich tat es sich auf der 2. Build gekotzt Jut und ich musste manuell löschen _skbuild
Verzeichnis jedes Mal , um es an fehlerfrei laufen.
Cool. Entschuldigung, dass Enscons aktualisiert wurde und rsalette nicht.
Am Mittwoch, 6. Mai 2020, um 16:18 Uhr schrieb Donald Stufft:
Ich habe versucht, Enscons zu testen, aber ich konnte rsalette nicht ohne Fehler erstellen.
Ich habe versucht , zu Test scikit-build zu sehen , wie es behandelt inkrementelle baut, und egal , was ich tat es sich auf der 2. Build gekotzt Jut und ich musste manuell löschen
_skbuild
Verzeichnis jedes Mal , um es an fehlerfrei laufen.
—
Sie erhalten dies, weil Sie einen Kommentar abgegeben haben.
Antworten Sie direkt auf diese E-Mail, zeigen Sie sie auf GitHub https://github.com/pypa/pip/issues/7555#issuecomment-624867490 an oder melden Sie sich ab https://github.com/notifications/unsubscribe-auth/AABSZERIEDAPUIXCPAKBBUDRQHAXRANCNFSM4KCV5MHQ .
Entschuldigung, dass Enscons aktualisiert wurde und rsalette nicht.
Gibt es eine gute C ext, die enscons verwendet, die aktualisiert wird? Ich habe mich nur für Rsalette entschieden, weil es an erster Stelle in der Liste stand und keine Lust hatte, es zu debuggen, und ich bin glücklich, es mit etwas anderem zu versuchen.
Das einzige Problem mit rsalette
ist, dass ROOT_IS_PURELIB
an Environment in SConstruct übergeben werden sollte. Es hat keine C-Erweiterung. cryptacular
sieht gut aus.
Damit bin ich, denke ich, einverstanden, dass wir diese Änderung rückgängig machen sollten.
Ich denke, die neuen Probleme sind viel größer als erwartet. Vielleicht ein kurzes 20.1.1 zum Zurücksetzen und dann können wir eine längere Diskussion darüber führen, wie sowohl die Probleme von In-Tree- als auch Out-of-Tree-Builds gelöst werden können?
Ich stimme auch für zurück und verfolge https://discuss.python.org/t/proposal-adding-a-persistent-cache-directory-to-pep-517-hooks/2303/15 als Lösung dafür (das würde zulassen, dass Back-Ends nicht direkt erstellt werden, sodass solche Probleme nicht offengelegt werden). Melden Sie sich auch in diesem Thread an, wenn Sie dem Vorschlag dort zustimmen.
Das erscheint mir auch sinnvoll. Ich denke, dass ein In-Tree- (oder Build-from-sdist)-Ansatz einige äußerst bedeutende Vorteile hat (ich bin mir ziemlich sicher, dass wir von einem Teil der Benutzerbasis Klageschreie bekommen werden, wenn wir zurückkehren 🙂), aber die Nachteile sind es auch wesentlich.
Mir ist nicht klar, wie die Benutzeroberfläche hier sein sollte (Standard: Welcher Ansatz? Welche Optionen sollten wir haben?), aber ich denke, wir sollten uns etwas mehr Zeit nehmen, um das zu entscheiden, anstatt Entscheidungen zu treffen, während wir die aktuellen Probleme bekämpfen .
In Ordnung! Ich denke, der allgemeine Konsens besteht darin, umzukehren und neu zu bewerten. Ich werde eine PR dafür einreichen. :)
Melden Sie sich auch in diesem Thread an, wenn Sie dem Vorschlag dort zustimmen.
Bitte tun Sie es - ich habe Kommentare abgegeben, aber ich bin an einem Punkt angelangt, an dem ich nicht genug weiß, um sinnvolle Vorschläge zu machen, daher wäre der Input von Leuten mit mehr Erfahrung wertvoll.
Habe gerade ein paar Big-Blobs-of-Text in https://github.com/pypa/pip/issues/8165#issuecomment -625401463 abgelegt. Ich gehe jetzt für heute weg... Am Ende war ich etwas frustriert, als ich die persönlichen Notizen schrieb. Auf #5599 zu landen und negative Benutzerkommentare zu lesen, hat sicherlich nicht geholfen.
Hallo Leute, ich habe mir noch einige Gedanken gemacht, hier ist mein aktueller Standpunkt zu diesem Thema.
- Bauen Sie ein sdist an Ort und Stelle, entpacken Sie das sdist an einem temporären Ort und bauen Sie dann daraus.
Ich glaube immer noch, dass Pip Install / Pip Wheel nicht der richtige Ort ist, um schlechte Sdists zu fangen. Sollte das nicht eine Backend-Verantwortung sein, um überhaupt keine schlechten Sdists zu erstellen? Außerdem würde ich denken, dass der bedingungslose Build über sdist wahrscheinlich genauso störend ist wie der Build an Ort und Stelle.
- Fügen Sie eine Pip-Option hinzu, um an Ort und Stelle zu bauen.
Das gefällt mir kurzfristig am besten, da Lösung 4 es nicht geschafft hat. Ist es verfrüht, das in Pip 20.1.1 hinzuzufügen?
- Aktualisieren Sie PEP 517 mit einer Art Mechanismus, damit Back-Ends mit Front-Ends kommunizieren können, wenn sie für In-Place-Builds "sicher" sind.
Mit diesem Pip müsste man immer noch auf seinen kaputten und nicht reparierbaren Copytree zurückgreifen, also bin ich nicht für diesen.
- Ändern Sie Pip, um immer an Ort und Stelle zu bauen.
Dieser wird also als zu störend erachtet und wir werden in 20.1.1 zurückkehren.
- Ändern Sie pip so, dass es standardmäßig an Ort und Stelle erstellt wird, mit einer Option zum Erstellen außerhalb des Baums.
Das könnte das langfristige Ziel sein, die Option, Out-of-Tree-Blending mit dem Cache-Verzeichnis-Konzept aufzubauen?
Ich mag CLI-Optionen wirklich nicht, besonders solche wie diese. Was passiert, wenn ich zwei Pakete aufliste, die sich auf meinem lokalen FS befinden, und ich eines an Ort und Stelle erstellen muss und eines nicht? Wenn wir eine Option für das eine oder andere anbieten, werden am Ende vorhandene Pakete entstehen, die nur mit dem einen oder anderen erstellt werden können.
Es riecht für mich auch nach einer Option, die nur deshalb existiert, weil ein Projekt keine Entscheidung treffen konnte und diese Entscheidung einfach an den Endbenutzer weitergegeben wurde.
Beim Bauen über sdist geht es nicht gerade darum, schlechte sdists zu fangen. Im Wesentlichen geht es darum, die möglichen Variationen des "Pfads" zu reduzieren, die ein Projekt durchlaufen kann, bevor es installiert wird. Das Hinzufügen eines Flags in gewisser Weise macht dieses Problem schlimmer und nicht besser.
Für das, was ich meine, haben wir ein paar "Pfade", die Installationen durchlaufen können:
Es gibt einige zusätzliche Pfade, die auslaufen, aber im Allgemeinen sind dies unsere 3 (und idealerweise wird auch 3 auslaufen). Es gibt auch bearbeitbare Installationen, die jedoch nicht so schnell verschwinden.
Wir können uns vorstellen, dass entweder ein sdist oder ein Rad auf PyPI hochgeladen und von dort installiert wird, bis es Teil desselben "Pfads" ist, Sie pausieren es einfach und beenden es auf einem anderen Computer.
Das Problem bei der Verwendung mehrerer solcher "Pfade" besteht darin, dass es Inkonsistenzen in der endgültigen resultierenden Installation gibt. Sie passieren nicht immer, aber es ist ein leicht zu beobachtender Fall, dass es häufig vorkommt. Oft sind diese Inkonsistenzen keine große Sache, aber manchmal sind sie es.
Wenn wir solche In-Place-Builds machen, dann sagen wir im Grunde, dass wir nie in der Lage sein werden, auf einen einzigen Pfad zusammenzubrechen, und wir müssen uns einfach immer mit diesem seltsamen Randfall auseinandersetzen, in dem manchmal Benutzer erhalten unterschiedliche Ergebnisse, je nachdem, wie die Installation durchgeführt wurde.
Als zusätzlicher Vorteil kann dies auch als Zwangsfunktion dienen, um sicherzustellen, dass der glückliche Weg glücklich bleibt.
Meistens stimme ich @dstufft zu , und insbesondere stimme ich zu, dass der Build-from-sdist-Ansatz nicht als "Versuch, sdists zu validieren" angesehen werden sollte, sondern als "alles folgt dem "Quellbaum -> sdist -> Rad -> Route installieren". (nur einige Dinge überspringen einige anfängliche Schritte)".
Einen Punkt möchte ich jedoch ansprechen:
Was passiert, wenn ich zwei Pakete aufliste, die sich auf meinem lokalen FS befinden, und ich eines an Ort und Stelle erstellen muss und eines nicht?
Führen Sie einfach die beiden Pakete in zwei separaten Pip-Läufen mit unterschiedlichen Optionen aus?!? Ich weiß , es ist möglich , eine eine Abhängigkeit des anderen ist und Ihr Punkt im Allgemeinen hält, aber es scheint eine allgemeine Neigung zu sein für die Menschen davon ausgehen , dass jedes installieren Szenario in einem einzigen Durchlauf von pip kollabiert werden muss, und ich don‘ Ich denke nicht, dass es vernünftig ist (wir hatten vollkommen gute Problemumgehungen für Probleme, die vom Benutzer abgelehnt wurden, weil "das bedeutet, dass ich meine Anforderungsliste in zwei Teile aufteilen müsste")
Beachten Sie, dass wir beim Zurücksetzen Probleme wie #6276, die aufgrund der Implementierung von In-Tree-Builds geschlossen wurden, erneut öffnen müssen.
Ein Teil des Problems ist, dass pip beim Auflösen von Abhängigkeiten nicht berücksichtigt, was bereits installiert ist (ich bin mir nicht sicher, ob die neue Resolver-Funktion das ändert?). Sie müssen also alles in einem einzigen pip-Aufruf enthalten, wenn Sie es auflösen möchten Abhängigkeiten "richtig" (sofern unser aktueller Resolver alles richtig macht).
Wenn der neue Resolver berücksichtigt, was bereits installiert ist, wären pip install foo bar
und pip install foo && pip install bar
ungefähr gleich und völlig egal, aber wenn nicht (und dasselbe gilt jetzt ungefähr) Wenn beide Projekte von "Spam" abhängen, aber foo erforderlich < 2 und bar erforderlich > 1 sind, erhalten wir eine ungültige Installation.
Das ist aber eine Tangente :)
(Ich bin mir nicht sicher, ob die neue Resolver-Arbeit das ändert?)
Eingaben willkommen auf #7744. :)
- Ändern Sie Pip, um immer an Ort und Stelle zu bauen.
Dieser wird also als zu störend erachtet und wir werden in 20.1.1 zurückkehren.
Um es klar zu sagen, wir haben es auch "zu schnell eingeführt" und der von uns gewählte Rollout-Ansatz ist definitiv ein Grund dafür, dass dies zu störend war.
- Fügen Sie eine Pip-Option hinzu, um an Ort und Stelle zu bauen.
@dstufft @pfmoore Ich sehe diese Art von Option als Opt-In-Mechanismus, damit wir Benutzer schrittweise zu In-Place-Builds https://github.com/pypa/pip/issues/8165#issuecomment -625501216
Ich werde eine PR dafür einreichen. :)
20.1.1 wurde veröffentlicht und enthält die rückgängig gemachten Änderungen.
Wenn wir in Fedora Python-RPM-Pakete erstellen, sind wir Dinosaurier und der Standardweg ist die Verwendung von
python setup.py build
. Mit PEP 517 haben wir stattdessen eine "vorläufige" Möglichkeit hinzugefügt,pip wheel
verwenden. Bei Erweiterungsmodulen haben wir jedoch ein Problem mit dem Ansatz "Quellen nach tmp verschieben, von dort erstellen", den pip verwendet, um sie zu erstellen.Unsere Build-Maschinerie fügt einige Compiler-Flags ein, sodass die Build-Artefakte (in diesem Fall
.so
Erweiterungsmodule) Metadaten über ihre Quellen enthalten. Später gibt es ein Shell-Skript, das die Build-Artefakte durchläuft, diese Informationen extrahiert und die Quellen nach/usr/src/debug
kopiert, um sie über ein spezielles*-debugsource
RPM zu installieren. Die Maschine erwartet, dass alles innerhalb des Arbeitsbaums gebaut wird und es funktioniert nicht wirklich gut, wenn es draußen gebaut wird. Hier sind die Dinge, die (gemeinsam) getan werden können, um das Problem auf unserer Seite zu mildern:1. set the `$TMPDIR` environment variable to have it within the place where the RPM script expects it (i.e. `export TMPDIR=%{_builddir}/.tmp` (and create it)) 2. use `pip wheel` with the `--no-clean` option to keep the copied sources in `$TMPDIR` 3. run some shell kung fu to rewrite the "what is my source" information to the correct location: `find %{buildroot} -iname '*.so' -print0 | xargs --no-run-if-empty -0 -n1 /usr/lib/rpm/debugedit -b "%{_builddir}/.tmp/pip-req-build-"* -d "$PWD"` 4. (Optional: clean `$TMPDIR` manually.)
Dies ist effektiv der Weg, den ich eingeschlagen habe, als ich die Pip-Integration, #6505 usw.
Iterative Builds mit pip werden heute effektiv gebrochen, was ein großer Verlust für Gruppen ist, die eine große Menge an Python-Code in C-Erweiterungsform haben, daher habe ich den Build mit setup.py
.
pip
benötigt einen build
Befehl und das Endergebnis des build
Befehls sollte an andere Unterbefehle weitergegeben werden können, wie wheel
, install
, etc.
Im Moment behandelt pip
install
pip
effektiv als build
und install
, was einige Leute _nicht_ wollen, die binäre Artefakte erstellen und zwischenspeichern und Binärdateien über Lesen installieren - nur Halterungen usw.
Ich wünschte wirklich, es gäbe eine Möglichkeit, setup.py
zu verwenden, um die Binärdateien zu erstellen, und dann pip install
sie zu erstellen, ohne ein bdist
erstellen zu müssen, aber das scheint heute nicht möglich zu sein , da pip
und distutils
/ setuptools
nicht übereinstimmen, wo die binären Artefakte zu finden sind.
Ich wünschte wirklich, es gäbe eine Möglichkeit, setup.py zu verwenden, um die Binärdateien zu erstellen, und dann mit pip zu installieren, ohne einen bdist zu erstellen, aber das scheint heute nicht möglich zu sein, da pip und distutils/setuptools nicht übereinstimmen wo die binären Artefakte zu finden sind.
Ich bin mir nicht sicher, ob ich dem folge - Sie sagen, dass Sie eine Möglichkeit zur Verwendung von Binärdateien wünschen, aber nicht die bereits vorhandenen binären Distributionsformate verwenden möchten. Warum ist das so?
Ich wünschte wirklich, es gäbe eine Möglichkeit, setup.py zu verwenden, um die Binärdateien zu erstellen, und dann mit pip zu installieren, ohne einen bdist zu erstellen, aber das scheint heute nicht möglich zu sein, da pip und distutils/setuptools nicht übereinstimmen wo die binären Artefakte zu finden sind.
Ich bin mir nicht sicher, ob ich dem folge - Sie sagen, dass Sie eine Möglichkeit zur Verwendung von Binärdateien wünschen, aber nicht die bereits vorhandenen binären Distributionsformate verwenden möchten. Warum ist das so?
Die bdist-Formate sind extrem einschränkend. Meine Gruppe muss auf ein dummes Format wie tar zurückgreifen und es dann wörtlich entpacken (keine der BSDs werden unterstützt, Debian wird nicht unterstützt usw.).
Was ich letzte Nacht entdeckt habe, ist, dass die Verwendung eines dummen bdist nicht über pip
installiert werden kann. Den dummen Binärdateien fehlen die Metadaten, die erforderlich sind, um über pip
, AFAICT installiert zu werden, wo ich denke, dass Pip Wheels ins Spiel kommen.
Ich habe es auch mit egg und zip versucht, aber ihnen fehlen die Metadaten, die für die Installation mit nur einem file://
URI erforderlich sind.
Ich habe mich damit beschäftigt, das Bauen über Distutils und Setuptools mit make in ein größeres Build-System zu integrieren, daher kann ich nicht sagen, ob ich "alle richtigen Dinge" getan habe, damit die Dinge so funktionieren wie ein Standard- bdist
Anruf hätte.
Von https://github.com/pypa/pip/issues/2195#issuecomment -664728481 kann ich sagen, dass ich mehr als glücklich bin, #7882 hinter --use-feature=in-tree-build
zu wiederholen.
Hurra! Klingt wie ein Plan!
Lassen Sie uns dieses Mal auch den Docstring von --build
aktualisieren. ;)
Ausgehend von #2195 (Kommentar) kann ich sagen, dass ich mehr als glücklich bin, #7882 hinter --use-feature=in-tree-build zu wiederholen.
Neugierig, ob es sinnvoll wäre, eine Option in-tree-build
in pyproject.toml
setzen, ebenso wie über die Befehlszeile? Dies wäre ziemlich gut, um #6276 aufzulösen, ohne ein Bash-Skript oder Makefile erstellen zu müssen, um Pip zu umhüllen. (Nicht, dass das ein besonders großes Problem wäre.)
eine In-Tree-Build-Option in pyproject.toml festlegen
@davidhewitt Dies ist mehr oder weniger Option 3 in der ursprünglichen Beschreibung dieses Problems. Nach meinem Verständnis ist der derzeitige Konsens, dass es besser ist, eine zusätzliche Option zu vermeiden, wenn wir können. Daher die Idee, In-Tree-Builds mit --use-feature
während einer Übergangszeit zu aktivieren, mit dem längerfristigen Ziel, es zum Standard- und einzigen Mechanismus zu machen.
Übrigens, ich werde dies nicht rechtzeitig zum 20.3 implementieren können, aber ich habe es immer noch vor, es hoffentlich in 20.4 zu tun.
@sbidoul Ich habe einen Patch geschrieben, um diese Funktion zu erhalten - siehe # 9091.
Hilfreichster Kommentar
Von https://github.com/pypa/pip/issues/2195#issuecomment -664728481 kann ich sagen, dass ich mehr als glücklich bin, #7882 hinter
--use-feature=in-tree-build
zu wiederholen.