Following system colour scheme Selected dark colour scheme Selected light colour scheme

Python Enhancement Proposals

PEP 778 – Unterstützung von Symlinks in Wheels

Autor:
Emma Harper Smith <emma at python.org>
Sponsor:
Barry Warsaw <barry at python.org>
PEP-Delegate:
Paul Moore <p.f.moore at gmail.com>
Discussions-To:
Discourse thread
Status:
Verschoben
Typ:
Standards Track
Thema:
Packaging
Benötigt:
777
Erstellt:
18. Mai 2024
Post-History:
10-Oct-2024

Inhaltsverzeichnis

Zusammenfassung

Wheels verarbeiten Symlinks derzeit nicht gut und kopieren den Inhalt anstelle der Erstellung von Symlinks bei der Installation. Um Bibliotheken in Wheels ordnungsgemäß zu verteilen, schlagen wir eine neue Metadatendatei LINKS vor, um Symlinks auf plattformübergreifende Weise zu handhaben. Diese Spezifikation erfordert eine neue Hauptversion von Wheels, wie in PEP 777 diskutiert.

PEP Verschiebung

Dieser PEP wurde aufgeschoben, bis eine bessere Kompatibilitätsstory für größere Änderungen am Wheel-Format etabliert ist. Sobald eine Kompatibilitätsstory für Wheels etabliert ist, die abwärtskompatible Verhaltensweisen auf unauffällige Weise ermöglicht, sollten die folgenden Punkte in diesem PEP behandelt werden

  • Fokussieren Sie dieses Thema erneut nur auf Symlinks für gemeinsame Bibliotheken auf POSIX-Plattformen, vielleicht gebunden an Plattform-Tags?
  • Sollen die Symlinks als Dateiattribute im Archiv oder als LINKS-Datei materialisiert werden? Könnte es in RECORD kodiert werden?
  • Klären Sie, dass dieser PEP nicht ausreicht, um für PEP 660 editierbare Installationen nützlich zu sein, da er nicht mehr plattformübergreifend sein wird.
  • Beschreiben Sie das Fallback-Verhalten in Fällen, in denen Symlinks auf POSIX-Plattformen nicht verfügbar sind.

Motivation

Heute werden Symlinks in Wheels als Kopien von Dateien erstellt, da das zipfile-Modul in CPython aus Sicherheitsgründen keine Unterstützung für die In-Place-Bearbeitung von Symlinks bietet.

Dies stellt Probleme für Projekte dar, die große kompilierte Bibliotheken in Wheels versenden möchten, da sie entweder die Installationsgröße des Projekts auf der Festplatte erheblich erhöhen oder den Symlink weglassen und möglicherweise einige nachgelagerte Anwendungsfälle beeinträchtigen müssen.

Um eine Bibliothek zu versenden, die für die Laufzeitnutzung oder die Linker-Zeit-Bindung auf POSIX ordnungsgemäß geladen werden kann, sollte eine Bibliothek die Konventionen des POSIX-Stil-Loaders und Linker-Suchpfads befolgen. Die beiden Hauptdateinamen, die der Loader verwendet, sind der „soname“ und der „echte Name“. Der „soname“ ist eine Datei wie libfoo.so.3, wobei 3 eine Zahl ist, die erhöht wird, wenn sich die Schnittstelle der Bibliothek ändert. Der „echte Name“ ist eine Datei wie libfoo.so.3.1.4, wobei die zusätzliche Versionsinformation den Loader findet eine bestimmte Version einer Bibliothek ermöglicht. Schließlich sucht der Linker beim Kompilieren von Code, der gegen eine Bibliothek gelinkt wird, nach einem „Linkernamen“, der wie libfoo.so benannt ist. Eine detailliertere Beschreibung finden Sie in dieser Linux-Dokumentation zu Shared Libraries. Um alle Laufzeit- und Linker-Zeit-Anwendungsfälle vollständig zu unterstützen, muss ein Projekt alle 3 Dateien versenden. Normalerweise wird dies auf POSIX-Plattformen durch die Verwendung von Symlinks gehandhabt, sodass die Bibliothek nicht dreimal auf der Festplatte dupliziert wird.

Zurück zur Python-Paketierung: Es gibt viele beliebte Projekte, die Binärbibliotheken versenden, wie z. B. numpy, scipy und pyarrow. Andere dlopen-Bibliotheken in anderen Wheels, wie z. B. pytorch und jax. Diese Projekte verlassen sich derzeit auf eine einzelne Bibliothek im Wheel, aber dies kann dazu führen, dass der Linker die falsche Bibliothek findet, wenn Systembibliotheken mit einer verfügbaren „echten Namen“-Bibliotheksversion vorhanden sind.

Es gibt auch den potenziellen Vorteil, dass Symlinks in Wheels einfachere editierbare Installationen ermöglichen würden, indem einfach ein Symlink im Verzeichnis site-packages des Benutzers platziert wird, aber dieser PEP belässt dies als offene Frage, die in einem zukünftigen PEP untersucht werden soll.

Begründung

Um die 3 Hauptbenennungen einer Bibliothek zu unterstützen, die beim Laden und Verlinken von Bibliotheken auf POSIX verwendet werden, schlagen wir vor, die Unterstützung für Symlinks in Python Wheels hinzuzufügen. Um die erstellten Symlinks verfolgen zu können und potenziell andere Plattformen zu unterstützen, die POSIX-Symlinks möglicherweise nicht direkt unterstützen, schlagen wir die Verwendung einer neuen Wheel-Metadatendatei LINKS vor, die sich im Verzeichnis .dist-info neben METADATA, RECORD und anderen Metadatendateien befindet.

Die Verwendung einer LINKS-Datei ermöglicht eine plattformübergreifendende Nutzung von Symlink-ähnlicher Funktionalität. Unter Windows erfordern Symlinks entweder eine Gruppenrichtlinie, die dem Benutzer erlaubt, Symlinks zu erstellen (z. B. durch Aktivieren von Dev-Modus) oder Administratorrechte. Das bedeutet, dass Symlinks auf einigen Benutzersystemen möglicherweise nicht unterstützt werden. Durch die Verwendung einer LINKS-Datei können Installierer potenziell andere Methoden zur Handhabung von Symlinks verwenden, wie z. B. Junctions unter Windows, wo der Installer andernfalls fehlschlagen müsste.

Dieser PEP beschreibt auch Prüfungen, die Installierer beim Installieren eines aktualisierten Wheels durchführen müssen. Diese Prüfungen dienen dazu, Sicherheitsrisiken zu bewältigen, die durch die Erlaubnis von Wheels zur Installation von Symlinks entstehen. Weitere Informationen zur Bedeutung dieser Prüfungen finden Sie unter Sicherheitsimplikationen.

Spezifikation

Erhöhung der Wheel-Hauptversion

Dieser PEP erfordert eine Erhöhung der Hauptversion von Wheels. Daher **MUSS** die Wheel-Version für mit LINKS generierte Wheels mindestens Version 2.0 sein, damit ältere Installierer nicht stillschweigend fehlschlagen, Symlinks zu installieren, und Benutzerumgebungen beschädigen. Mehr dazu siehe PEP 777.

Spezifikation des Installer-Verhaltens

Installierer **MÜSSEN** die Pfade aller in der LINKS-Datei enthaltenen Links auflösen, *bevor* sie entscheiden, ob ein quellpfad oder zielpfad gültig ist. Installierer **MÜSSEN** überprüfen, ob quellpfad und zielpfad innerhalb eines Namespace oder Pakets aus dem Wheel liegen. Installierer **MÜSSEN** zyklische Symlinks in Wheels ablehnen. Installierer **KÖNNEN** einen Fehler ausgeben, wenn eine lange Kette von Symlinks (Symlinks, die mehrmals auf Symlinks zeigen) ein vom Installer festgelegtes Limit überschreitet.

Installierer **MÜSSEN** die folgenden Schritte ausführen, wenn sie ein Wheel mit Symlinks verarbeiten:

  1. Prüfen Sie auf das Vorhandensein einer LINKS-Datei im .dist-info-Verzeichnis. Wenn sie nicht existiert, sind keine weiteren Schritte erforderlich.
  2. Extrahieren Sie alle Dateien in den Wheel-Paketen und dem Datenverzeichnis wie bei Wheel 1.x.
  3. Überprüfen Sie, dass für jedes Paar quellpfad und zielpfad der zielpfad in einem der gerade extrahierten Paket-Namespaces existiert.
  4. Prüfen Sie anschließend, ob der Installer auf dem aktuellen System eine Art von Link für jedes Paar im Site-Verzeichnis erstellen kann. Wenn der Installer keinen Link für die Datei/den Ordner zielpfad erstellen kann, **MUSS** ein Fehler ausgelöst werden. Ein Beispiel für einen Fehlerfall wäre ein POSIX-Symlink auf ein Dateiziel, wobei der Installer unter Windows läuft und keine Symlinks erstellen kann, aber Junctions erstellen kann. In diesem Fall **MUSS** der Installer einen Fehler ausgeben, da er den Link nicht handhaben kann.
  5. Schließlich **MUSS** der Installer einen plattformrelevanten Link zwischen quellpfad und zielpfad erstellen.

Installierer **DÜRFEN** Dateien nicht standardmäßig kopieren, anstatt einen Symlink zu erstellen, wenn sie Symlinks verarbeiten. Installierer **KÖNNEN** ein solches Verhalten unter einer alternativen Konfiguration oder einem Kommandozeilenflag anbieten.

Spezifikation des Build-Backends

Beim Erstellen eines Wheels **MÜSSEN** Build-Backends Symlinks genauso behandeln wie deren Ziele, wenn sie entscheiden, ob der Symlink in ein Wheel aufgenommen werden soll. Build-Backends **MÜSSEN** überprüfen, ob in der LINKS-Datei keine hängenden Symlinks vorhanden sind. Build-Backends **SOLLTEN** plattformrelevante Symlinks erkennen, die in Builds aufgenommen werden würden. Auf POSIX-Systemen sind dies typischerweise Symlinks, unter Windows gehören dazu Symlinks und Junctions.

Abwärtskompatibilität

Die Einführung von Symlinks würde eine Erhöhung der Hauptversion des Wheel-Formats erfordern. Das bedeutet, dass neue Wheels, die das neue Wheel-Format verwenden, bei älteren Installer-Tools einen Fehler auslösen würden, gemäß der Wheel-Spezifikation.

Bitte siehe PEP 777 zu „Wheel 2.0“.

Sicherheitsimplikationen

Symlinks können ziemlich gefährlich sein, wenn sie nicht sorgfältig behandelt werden. Ein einfaches Beispiel wäre, wenn ein Benutzer sudo pip install malicious ausführt und keine Schutzmaßnahmen vorhanden sind, dann könnte das bösartige Paket /etc/shadow überschreiben und den Passwort-Hash auf dem System ersetzen, was bösartige Anmeldungen ermöglicht.

Dieser PEP listet mehrere Anforderungen an Prüfungen auf, die von Installern für Symlinks in Wheels durchgeführt werden müssen, um sicherzustellen, dass Angriffe wie der oben beschriebene nicht stattfinden können. Das bedeutet, dass es **entscheidend** ist, dass Installierer diese Sicherheitsvorkehrungen sorgfältig implementieren und bösartige Nutzung bei der Paketinstallation verhindern.

Insbesondere **MÜSSEN** die folgenden Prüfungen von Installern durchgeführt werden:

  1. Dass die Symlinks nicht außerhalb von Paketen oder Namespaces, die aus dem Wheel stammen, zeigen.
  2. Dass die Symlinks nicht hängen (das Ziel existiert zum Zeitpunkt der Installation).
  3. Dass die Symlinks nicht zyklisch sind, wobei nach einer bestimmten Prüftiefe angehalten wird, um Denial-of-Service-Anfragen zu vermeiden.

Beim Entfernen keine Symlinks folgen.

Wie man das lehrt

Endbenutzer sollten, sobald die Änderungen im Ökosystem angekommen sind, transparent die Vorteile von Symlinks in Wheels erfahren. Es ist wichtig, dass Installierer klare Fehlermeldungen liefern, wenn Symlinks auf der Plattform nicht unterstützt werden, und erklären, warum die Installation fehlgeschlagen ist.

Für Personen, die Bibliotheken erstellen, sollte die Dokumentation auf packaging.python.org die Anwendungsfälle und Vorbehalte (insbesondere Plattformunterstützung) von Symlinks in Wheels beschreiben. Andernfalls sollte dies transparent von Build-Backends genauso gehandhabt werden wie jeder normale Dateiname.

Referenzimplementierung

TODO

Abgelehnte Ideen

Bibliotheksmaintainer sollten Python zur Lokalisierung von Bibliotheken verwenden

Die Verwendung von Python zur Lokalisierung von Bibliotheken wäre viel einfacher. Einige Bibliotheken wie libtorch werden jedoch von Erweiterungsmodulen verwendet und erfordern selbst das Laden von Abhängigkeiten. Einige kompilierte Bibliotheken können Python nicht verwenden, um ihre Loader-Abhängigkeiten zu finden.

Offene Fragen

PEP 660 und Verschiebung der Unterstützung für Editierbare Installationen

Dieser PEP lässt die Spezifikation und Implementierung eines PEP 660 editierbaren Installationsmechanismus ungelöst für einen späteren PEP; sollte dies in diesem PEP spezifiziert werden?

Sicherheit

Dieser PEP muss überprüft werden, um sicherzustellen, dass er keine neuen Sicherheitslücken zulässt. Gibt es weitere Einschränkungen, die wir für die Quelle oder das Ziel von Symlinks festlegen sollten, um Benutzer zu schützen?

Frühere Diskussion

https://discuss.python.org/t/symbolic-links-in-wheels/1945/25


Quelle: https://github.com/python/peps/blob/main/peps/pep-0778.rst

Zuletzt geändert: 2025-07-09 03:07:54 GMT