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

Python Enhancement Proposals

PEP 648 – Erweitbare Anpassungen des Interpreters beim Start

Autor:
Mario Corchero <mariocj89 at gmail.com>
Sponsor:
Pablo Galindo
Discussions-To:
Discourse thread
Status:
Abgelehnt
Typ:
Standards Track
Erstellt:
30-Dez-2020
Python-Version:
3.11
Post-History:
16-Dez-2020, 18-Dez-2020

Inhaltsverzeichnis

Zusammenfassung

Dieser PEP schlägt die Unterstützung für erweiterbare Anpassungen des Interpreters beim Start vor, indem Benutzern erlaubt wird, Dateien zu installieren, die beim Start ausgeführt werden.

Ablehnung der PEP

PEP 648 wurde vom Steering Council abgelehnt, da er eine begrenzte Anzahl von Anwendungsfällen hat und die Startsequenz weiter verkompliziert.

Motivation

Systemadministratoren, Werkzeuge, die den Interpreter neu verpacken, und einige Bibliotheken müssen Aspekte des Interpreters zur Startzeit anpassen.

Dies wird normalerweise über sitecustomize.py für Systemadministratoren erreicht, während Bibliotheken auf die Ausnutzung von pth-Dateien angewiesen sind. Dieser PEP schlägt einen Weg vor, die gleiche Funktionalität auf eine benutzerfreundlichere und strukturiertere Weise zu erreichen.

Einschränkungen von pth-Dateien

Wenn eine Bibliothek vor einem Import oder im Zusammenhang mit der allgemeinen Arbeitsweise des Interpreters Anpassungen vornehmen muss, verlässt sie sich oft darauf, dass pth-Dateien, die beim Start geladen und über das Site-Modul [7] implementiert werden, Python-Code enthalten können, der ausgeführt wird, wenn die pth-Datei ausgewertet wird.

Beachten Sie, dass pth-Dateien ursprünglich nur dazu entwickelt wurden, zusätzliche Verzeichnisse zu sys.path hinzuzufügen, aber sie können auch Zeilen enthalten, die mit „import“ beginnen, welche an exec() übergeben werden. Benutzer haben diese Funktion ausgenutzt, um die von ihnen benötigten Anpassungen zu ermöglichen. Sehen Sie setuptools [4] oder betterexceptions [5] als Beispiele.

Die Verwendung von pth-Dateien für diesen Zweck ist für Bibliotheksentwickler alles andere als ideal, da sie Code in eine einzige Zeile einfügen müssen, der ein Import vorangestellt ist, was ihn ziemlich unleserlich macht. Bibliotheksentwickler, die diese Praxis befolgen, erstellen normalerweise ein Modul, das alle Aktionen beim Import durchführt, wie von betterexceptions [5] getan, aber der Ansatz ist immer noch nicht wirklich benutzerfreundlich.

Darüber hinaus ist es auch nicht ideal für Benutzer des Interpreters, wenn sie inspizieren möchten, was beim Python-Start ausgeführt wird, da sie alle pth-Dateien auf potenzielle Codeausführung überprüfen müssen, die über alle Site-Pfade verteilt sein können. Die meisten dieser pth-Dateien werden „legitime“ pth-Dateien sein, die nur den Pfad modifizieren, und die Frage „Was verändert meinen Interpreter beim Start?“ wird zu einer eher komplexen Frage.

Schließlich gab es mehrere Vorschläge, die Codeausführung aus pth-Dateien zu entfernen, siehe [1] und [2].

Einschränkungen von sitecustomize.py

Während sitecustomize eine akzeptable Lösung ist, geht sie davon aus, dass eine einzelne Person für das System und den Interpreter verantwortlich ist. Wenn sowohl der Systemadministrator als auch die Verantwortung für die Bereitstellung des Interpreters Anpassungen zum Interpreterstart hinzufügen möchten, müssen sie sich über den Inhalt der Datei einigen und alle Änderungen kombinieren. Dies ist jedoch keine wesentliche Einschränkung und nicht der Haupttreiber dieser Änderung. Sollte die Änderung erfolgen, wird sie auch die Situation für diese Benutzer verbessern, da sie anstelle eines sitecustomize.py, das all diese Aktionen ausführt, isolierte benutzerdefinierte Dateien mit Namen haben können, die den Features entsprechen, die sie erweitern möchten. Ubuntu könnte beispielsweise sein aktuelles sitecustomize.py in ubuntu_apport_python_hook ändern. Dies repräsentiert nicht nur seine Absicht besser, sondern gibt Benutzern des Interpreters auch ein besseres Verständnis der Änderungen, die an ihrem Interpreter vorgenommen werden.

Begründung

Dieser PEP schlägt die Unterstützung für erweiterbare Anpassungen des Interpreters beim Start vor, indem alle Dateien, die in Verzeichnissen namens __sitecustomize__ in sitepackages [8] oder usersitepackages [9] gefunden werden, zur Startzeit ausgeführt werden.

Warum __sitecustomize__

Der Name soll dem bereits bestehenden Konzept von sitecustomize.py folgen. Da sich das Verzeichnis innerhalb von sys.path befindet, da es sich in den Site-Pfaden befindet, haben wir uns entschieden, doppelte Unterstriche um seinen Namen zu verwenden, um eine Kollision mit dem bereits vorhandenen sitecustomize.py zu vermeiden.

Entdecken der neuen Verzeichnisse __sitecustomize__

Der Python-Interpreter sucht beim Start nach einem Verzeichnis namens __sitecustomize__ innerhalb eines beliebigen der Standard-Site-Packages-Pfade.

Dies sind üblicherweise der Python-Systemstandort und der Benutzerstandort, werden aber letztendlich durch die Logik des Site-Moduls definiert.

Benutzer können site.sitepackages [8] und site.usersitepackages [9] verwenden, um die Pfade zu erfahren, in denen der Interpreter __sitecustomize__-Verzeichnisse entdecken kann.

Zeitpunkt der Entdeckung von __sitecustomize__

Die __sitecustomize__-Verzeichnisse werden genau nach dem Entdecken von pth-Dateien in einem Site-Packages-Pfad als Teil von site.addsitedir [10] entdeckt.

Dies wird für jeden der Site-Packages-Pfade in der exakt gleichen Reihenfolge wiederholt, die heute für pth-Dateien befolgt wird.

Reihenfolge der Ausführung innerhalb von __sitecustomize__

Die Implementierung wird die Dateien innerhalb von __sitecustomize__ ausführen, indem sie diese beim Entdecken jedes der __sitecustomize__-Verzeichnisse nach Namen sortiert. Wir raten den Benutzern jedoch von der Abhängigkeit von der Ausführungsreihenfolge ab.

Wir haben erwogen, sie in zufälliger Reihenfolge auszuführen, aber das könnte zu unterschiedlichen Ergebnissen führen, je nachdem, wie der Interpreter diese Dateien auswählt. Auch wenn es keine gute Praxis ist, sich auf die Ausführung anderer Dateien zu verlassen, denken wir, dass dies besser ist, als zufällig unterschiedliche Ergebnisse beim Interpreterstart zu haben. Wir haben uns entschieden, die Dateien nach den pth-Dateien auszuführen, falls ein Benutzer Elemente zum Pfad hinzufügen muss, bevor er eine Datei ausführt.

Interaktion mit pth-Dateien

pth-Dateien können verwendet werden, um Pfade zu sys.path hinzuzufügen, aber dies sollte den Entdeckungsprozess von __sitecustomize__ nicht beeinträchtigen, da diese Verzeichnisse ausschließlich in Site-Packages-Pfaden gesucht werden.

Ausführung von Dateien innerhalb von __sitecustomize__

Wenn ein __sitecustomize__-Verzeichnis entdeckt wird, werden alle Dateien mit der Erweiterung .py darin mit io.open_code gelesen und mit exec [11] ausgeführt.

An die exec-Funktion wird ein leeres Wörterbuch als globals übergeben, um unerwartete Interaktionen zwischen verschiedenen Dateien zu verhindern.

Fehlerbehandlung

Fehler bei der Ausführung einer der Dateien werden nicht protokolliert, es sei denn, der Interpreter wird im ausführlichen Modus ausgeführt, und sie sollten die Auswertung anderer Dateien nicht stoppen. Der Benutzer erhält eine Meldung in stderr, dass die Datei nicht ausgeführt werden konnte und dass der ausführliche Modus verwendet werden kann, um weitere Informationen zu erhalten. Dieses Verhalten ahmt das bestehende für sitecustomize.py nach.

Interaktion mit virtuellen Umgebungen

Die über die neuen __sitecustomize__-Lösungen auf einen Interpreter angewendeten Anpassungen funktionieren weiterhin, wenn ein Benutzer eine virtuelle Umgebung erstellt, genauso wie sitecustomize.py mit virtuellen Umgebungen interagiert.

Dies ist ein Unterschied zu pth-Dateien, die nicht in virtuelle Umgebungen übernommen werden, es sei denn, include-system-site-packages ist aktiviert.

Wenn Bibliotheksentwickler über __sitecustomize__ installierte Funktionen haben, die sie nicht in virtuelle Umgebungen übernehmen möchten, sollten sie erkennen, ob sie sich innerhalb einer virtuellen Umgebung befinden, indem sie sys.prefix == sys.base_prefix überprüfen. Dieses Verhalten ähnelt Paketen, die das globale sitecustomize.py modifizieren.

Interaktion mit sitecustomize.py und usercustomize.py

Bis zur Entfernung werden sitecustomize und usercustomize nach __sitecustomize__ ausgeführt, ähnlich wie pth-Dateien. Informationen zu Entfernungsplänen für sitecustomize und usercustomize finden Sie im Abschnitt Abwärtskompatibilität.

Identifizieren aller installierten Dateien

Um das Debugging des Python-Starts zu erleichtern, wird, wenn das Site-Modul aufgerufen wird, das __sitecustomize__-Verzeichnis, das beim Start entdeckt wird, ausgegeben.

Namenskonvention für Dateien

Pakete werden ermutigt, den Namen des Pakets in den Dateinamen aufzunehmen, um Kollisionen zwischen Paketen zu vermeiden. Die einzige Anforderung an den Dateinamen ist jedoch, dass er auf .py endet, damit der Interpreter ihn ausführen kann.

Deaktivieren von Startdateien

In einigen Szenarien, beispielsweise wenn die Startzeit entscheidend ist, kann es wünschenswert sein, diese Option vollständig zu deaktivieren. Das bereits vorhandene Flag -S [3] deaktiviert die gesamte site-bezogene Manipulation, einschließlich dieser neuen Funktion. Wenn das Flag übergeben wird, werden keine __sitecustomize__-Verzeichnisse entdeckt.

Zusätzlich wird, um den Interpreterstart zu ermöglichen und nur diese neue Funktion zu deaktivieren, eine neue Option unter -X hinzugefügt: disablesitecustomize, die die Entdeckung von __sitecustomize__ exklusiv deaktiviert.

Zuletzt kann der Benutzer die Entdeckung von __sitecustomize__-Verzeichnissen nur im Benutzer-Site deaktivieren, indem er den Benutzer-Site über eine der mehreren Optionen im site.py-Modul deaktiviert.

Unterstützung in Build-Backends

Obwohl Build-Backends eine Option anbieten können, um die Installation dieser Dateien in ein __sitecustomize__-Verzeichnis zu erleichtern, befasst sich dieser PEP nicht direkt damit. Ähnlich wie bei pth-Dateien können Build-Backends dafür entscheiden, keinen einfach zu konfigurierenden Mechanismus für __sitecustomize__-Dateien bereitzustellen und Benutzern zu erlauben, in den Installationsprozess einzugreifen, um solche Dateien einzubinden. Wir halten eine erweiterte Unterstützung durch Build-Backends nicht für eine Anforderung dieses PEP.

Auswirkungen auf die Startzeit

Ein Bedenken bei dieser Implementierung ist, wie sich die Startzeit des Python-Interpreters durch diese Ergänzung beeinflussen lässt. Wir erwarten, dass die Leistungsauswirkung stark von der Logik in den Dateien abhängt, die ein Benutzer oder Systemadministrator in der zu testenden Python-Umgebung installiert.

Wenn der Interpreter Dateien in seinem __sitecustomize__-Verzeichnis hat, werden die Ausführungszeit der Datei plus ein Aufruf zum Lesen des Codes zur Startzeit hinzugefügt. Dies ähnelt der Art und Weise, wie die Codeausführung die Startzeit durch sitecustomize.py, usercustomize.py und Code in pth-Dateien beeinflusst. Wir werden uns daher hier auf den Vergleich dieser Lösung mit diesen drei konzentrieren, da die tatsächliche hinzugefügte Zeit zur Startzeit ansonsten stark vom auszuführenden Code in diesen Dateien abhängt.

Die Ergebnisse wurden durch Ausführen von „./python.exe -c pass“ mit perf über 50 Iterationen und Wiederholung des Befehls 50 Mal pro Iteration und Ermittlung des geometrischen Mittelwerts aller Ergebnisse gewonnen. Die Datei, die zum Ausführen dieser Benchmarks verwendet wurde, ist in der Referenzimplementierung [6] eingecheckt.

Der Benchmark wurde mit 3.10 Alpha 7, kompiliert mit PGO und LTO, mit den folgenden Parametern und Systemzustand ausgeführt

  • Perf-Ereignis: Maximale Abtastrate auf 1 pro Sekunde eingestellt
  • CPU-Frequenz: Minimale Frequenz der CPU 17,35 auf die maximale Frequenz eingestellt
  • Turbo Boost (MSR): Turbo Boost auf CPU 17 deaktiviert: MSR 0x1a0 auf 0x4000850089 gesetzt
  • IRQ-Affinität: Standardaffinität auf CPU 0-16,18-34 gesetzt
  • IRQ-Affinität: Affinität von IRQ 1,3-16,21,25-31,56-59,68-85,87,89-90,92-93,95-104 auf CPU 0-16,18-34 gesetzt
  • CPU: Verwende 2 logische CPUs: 17,35
  • Perf-Ereignis: Maximale Abtastrate: 1 pro Sekunde
  • ASLR: Vollständige Randomisierung
  • Linux-Scheduler: Isolierte CPUs (2/36): 17,35
  • Linux-Scheduler: RCU auf CPUs (2/36) deaktiviert: 17,35
  • CPU-Frequenz: 0-16,18-34=min=1200 MHz, max=3600 MHz; 17,35=min=max=3600 MHz
  • Turbo Boost (MSR): CPU 17,35: deaktiviert

Der Code, der in pth-Dateien, sitecustomize.py, usercustomize.py und Dateien innerhalb von __sitecustomize__ ausgeführt werden soll, ist der folgende

import time; x = time.time() ** 5

Die Datei zielt darauf ab, eine einfache Operation auszuführen, die dennoch als vernachlässigbar gelten sollte. Dies soll das Experiment in eine Situation bringen, in der wir Leistungshits aufgrund des Mechanismus sichtbar machen und gleichzeitig relativ realistisch bleiben. Zusätzlich beginnt es mit einem Import und ist eine einzelne Zeile, die in pth-Dateien verwendet werden kann.

Test # Dateien Zeit (us)
# sitecustomize.py usercustomize.py pth __sitecustomize__ Lauf 1 Lauf 2
1 0 0 0 Verzeichnis nicht erstellt 13884 13897
2 0 0 0 0 13871 13818
3 0 0 1 0 13964 13924
4 0 0 0 1 13940 13939
5 1 1 0 0 13990 13993
6 0 0 0 2 (System + Benutzer) 14063 14040
7 0 0 50 0 16011 16014
8 0 0 0 50 15456 15448

Die Ergebnisse können mit dem Skript run-benchmark.py, das in der Referenzimplementierung [6] bereitgestellt wird, reproduziert werden.

Wir interpretieren Folgendes aus diesen Ergebnissen

  • Die Verwendung von zwei __sitecustomize__-Skripten im Vergleich zu sitecustomize.py und usercustomize.py verlangsamt den Interpreter um 0,3 %. Wir erwarten diese Verlangsamung, bis sitecustomize.py und usercustomize.py in einer zukünftigen Version entfernt werden, da der Interpreter versuchen wird, sie zu importieren, auch wenn der Benutzer die Dateien nicht erstellt.
  • Mit den willkürlichen 50 pth-Dateien mit getestetem Code führt die Verschiebung dieser in __sitecustomize__ zu einer Beschleunigung der Startzeit um ca. 3,5 %. Dies ist wahrscheinlich auf die einfachere Logik zur Auswertung von __sitecustomize__-Dateien im Vergleich zur Ausführung von pth-Dateien zurückzuführen.
  • Im Allgemeinen zeigen alle Messungen, dass diese Ergänzung eine geringe Auswirkung auf die Startzeit hat.

Audit-Ereignis

Ein neues Audit-Ereignis wird hinzugefügt und bei der Ausführung von __sitecustomize__ ausgelöst, um die Sicherheitsinspektion zu erleichtern, indem sys.audit [12] mit dem Namen „sitecustimze.exec_file“ und dem Dateinamen als Argument aufgerufen wird.

Sicherheitsimplikationen

Dieser PEP zielt darauf ab, die gesamte Codeausführung aus pth-Dateien in Dateien innerhalb eines __sitecustomize__-Verzeichnisses zu verlagern. Wir denken, dass dies eine Verbesserung für Systemadministratoren aus folgenden Gründen ist

  • Ermöglicht die schnelle Identifizierung des beim Start vom Interpreter ausgeführten Codes, indem nur ein Verzeichnis durchsucht wird, anstatt alle pth-Dateien zu scannen.
  • Ermöglicht die Nachverfolgung der Nutzung dieser Funktion über das neue vorgeschlagene Audit-Ereignis.
  • Gibt eine feinere Kontrolle, indem die Berechtigungen für das __sitecustomize__-Verzeichnis angepasst werden können, wodurch Benutzer möglicherweise nur Pakete installieren können, die den Interpreterstart nicht ändern.

Kurz gesagt, obwohl dies einem böswilligen Benutzer ermöglicht, eine Datei abzulegen, die beim Start ausgeführt wird, ist es eine Verbesserung gegenüber den bestehenden pth-Dateien.

Wie man dies lehrt

Dies kann so einfach dokumentiert und gelehrt werden, dass der Interpreter beim Start im Verzeichnis __sitecustomize__ in seinen Site-Pfaden sucht und, wenn er Dateien mit der Erweiterung .py findet, diese nacheinander ausführt.

Für Systemadministratoren und Werkzeuge, die den Interpreter verpacken, können wir jetzt empfehlen, Dateien in __sitecustomize__ zu platzieren, so wie sie früher sitecustomize.py platziert haben. Sie können sich darauf verlassen, dass ihr Inhalt nicht vom nächsten Benutzer überschrieben wird, da sie spezifische Dateien bereitstellen können, um die von ihnen gewünschte Logik zu verwalten.

Bibliotheksentwickler sollten in der Lage sein, ein neues Argument für Tools wie setuptools anzugeben, das diese neuen Dateien einfügt. So etwas wie sitecustomize_files=["scripts/betterexceptions.py"], was ihnen ermöglicht, diese hinzuzufügen. Sollte der Build-Backend dies nicht unterstützen, können sie sie manuell installieren, wie sie es früher mit pth-Dateien getan haben. Wir werden ihnen empfehlen, den Namen des Pakets als Teil des Dateinamens aufzunehmen.

Abwärtskompatibilität

Dieser PEP fügt eine Deprecation-Warnung für die Codeausführung von sitecustomize.py, usercustomize.py und pth in 3.11, 3.12 und 3.13 hinzu. Mit Plänen zur Entfernung dieser Funktionen bis 3.14. Die Migration von diesen Lösungen zu __sitecustomize__ sollte idealerweise nur die Verlagerung der Logik in eine andere Datei sein.

Während der bestehende Mechanismus sitecustomize.py auf Systemadministratoren abzielte, die ihn in einen Site-Pfad platzierten, konnte die Datei zum Zeitpunkt des Interpreterstarts tatsächlich überall im Pfad platziert werden. Der neue Mechanismus erlaubt es Benutzern nicht, __sitecustomize__-Verzeichnisse überall im Pfad zu platzieren, sondern nur in Site-Pfaden. Systemadministratoren können ein ähnliches Verhalten wie sitecustomize.py wiederherstellen, indem sie eine benutzerdefinierte Datei in __sitecustomize__ hinzufügen, die nur sitecustomize als Migrationspfad importiert.

Referenzimplementierung

Eine erste Implementierung, die die CPython-Testsuite besteht, steht zur Bewertung zur Verfügung [6].

Diese Implementierung ist nur für den Gutachter zum Ausprobieren und zur Überprüfung potenzieller Probleme gedacht, die dieser PEP verursachen könnte.

Abgelehnte Ideen

Nichts tun

Obwohl der aktuelle Status „funktioniert“ die in der Motivation aufgeführten Probleme aufweist. Nach Analyse der Auswirkungen dieser Änderung glauben wir, dass sie es wert ist, angesichts der verbesserten Erfahrung, die sie bietet.

Formalisierung der Verwendung von pth-Dateien

Eine andere Option wäre, die Verwendung von pth-Dateien zum Einfügen von Code beim Start zu verherrlichen und zu dokumentieren, aber das ist eine suboptimale Erfahrung für Benutzer, wie in der Motivation aufgeführt.

Machen von __sitecustomize__ zu einem Namespace-Paket

Wir erwogen, das Verzeichnis zu einem Namespace-Paket zu machen und einfach alle darin enthaltenen Module zu importieren, was die Suche über alle Pfade in sys.path bei der Initialisierung ermöglichte und eine Möglichkeit bot, Abhängigkeiten zwischen Dateien durch gegenseitigen Import zu deklarieren. Dies wurde aus mehreren Gründen abgelehnt

  1. Dies verbreiterte unnötigerweise die Liste der Pfade, auf denen willkürliche Dateien ausgeführt werden.
  2. Die Logik brachte zusätzliche Komplexität, wie z. B. was zu tun ist, wenn ein Paket eine __init__.py-Datei an einem der Orte installiert.
  3. Es ist günstiger, nach __sitecustomize__ zu suchen, da wir bereits nach pth-Dateien in den Site-Pfaden suchen, im Vergleich zur tatsächlichen Ausführung eines Namespace-Pakets.

Unterstützung für Shutdown-Anpassungen

init.d-Benutzer könnten versucht sein, diese Funktion so zu implementieren, dass Benutzer auch beim Herunterfahren Code hinzufügen können, aber zusätzliche Unterstützung dafür ist nicht erforderlich, da Python-Benutzer dies bereits über atexit tun können.

Verwendung von entry_points

Wir erwogen, die Verwendung von Entry-Points zu erweitern, um die Angabe von Dateien zu ermöglichen, die beim Start ausgeführt werden sollten, aber wir verwarfen diese Lösung aus zwei Hauptgründen. Der erste Grund ist die Auswirkung auf die Startzeit. Dieser Ansatz würde das Scannen aller Paketverteilungsinformationen erfordern, um nur eine Handvoll Dateien auszuführen. Dies hat Auswirkungen auf die Leistung, selbst wenn der Benutzer die Funktion nicht nutzt, und diese Auswirkungen wachsen linear mit der Anzahl der in der Umgebung installierten Pakete. Der zweite Grund war, dass die in diesem PEP vorgeschlagene Implementierung eine einzige Lösung für die Startzeitanpassung für Pakete und Systemadministratoren bietet. Darüber hinaus kann die Angabe, wenn das Hauptziel von Entry-Points darin besteht, Bibliotheken die einfache Installation von Dateien beim Start zu ermöglichen, immer noch hinzugefügt werden und die Build-Backends einfach die Dateien in das __sitecustomize__-Verzeichnis installieren lassen.

Danksagungen

Danke an Pablo Galindo für seinen Beitrag zu diesem PEP und die Bereitstellung seines PCs zur Ausführung des Benchmarks.

Referenzen


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

Zuletzt geändert: 2025-02-01 08:55:40 GMT