PEP 534 – Verbesserte Fehler für fehlende Standardbibliothek-Module
- Autor:
- Tomáš Orsava <tomas.n at orsava.cz>, Petr Viktorin <encukou at gmail.com>, Alyssa Coghlan <ncoghlan at gmail.com>
- Status:
- Verschoben
- Typ:
- Standards Track
- Erstellt:
- 05-Sep-2016
- Post-History:
Inhaltsverzeichnis
- Zusammenfassung
- PEP Verschiebung
- Motivation
- Spezifikation
- Design-Diskussion
- Modifikation von
sys.excepthook - Öffentliche API zur Abfrage erwarteter Namen von Standardbibliothek-Modulen
- Nur Namen von Top-Level-Modulen einschließen
- Auflisten privater Top-Level-Modulnamen als optionale Standardbibliothek-Module
- Module im Zusammenhang mit Packaging als zwingend erforderlich einstufen
- Modifikation von
- Zurückgestellte Ideen
- Empfehlung für nachgelagerte Distributoren
- Abwärtskompatibilität
- Referenz und Beispielimplementierung
- Hinweise und Referenzen
- Urheberrecht
Zusammenfassung
Python wird oft ohne seine vollständige Standardbibliothek erstellt oder verteilt. Es gibt jedoch bisher keine standardisierte, benutzerfreundliche Methode, den Benutzer ordnungsgemäß über den fehlgeschlagenen Import solcher fehlender Standardbibliothek-Module zu informieren.
Dieser PEP schlägt einen Mechanismus vor, um erwartete Standardbibliothek-Module zu identifizieren und den Benutzern informativere Fehlermeldungen zu geben, wenn Importversuche von Standardbibliothek-Modulen fehlschlagen.
PEP Verschiebung
Die Autoren dieses PEP arbeiten nicht aktiv daran. Wenn Sie an der Verbesserung dieser Fehlermeldungen interessiert sind, kontaktieren Sie uns bitte! (z. B. durch Posten auf der python-dev Mailingliste).
Der wichtigste offene Punkt ist die Ermittlung, wie die Autoconf- und Visual Studio-Build-Prozesse die sysconfig-Metadatendatei mit den Listen der erwarteten und optionalen Standardbibliothek-Module befüllen.
Motivation
Es gibt mehrere Anwendungsfälle für die Aufnahme nur einer Teilmenge von Pythons Standardbibliothek. Bisher gibt es jedoch keinen benutzerfreundlichen Mechanismus, um den Benutzer darüber zu informieren, *warum* ein stdlib-Modul fehlt und wie die Situation entsprechend behoben werden kann.
CPython
Wenn eines der Standardbibliothek-Module von Python (wie z. B. _sqlite3) während eines CPython-Builds aufgrund fehlender Abhängigkeiten (z. B. SQLite-Header-Dateien) nicht kompiliert werden kann, wird das Modul einfach übersprungen. Wenn Sie dann dieses kompilierte Python installieren und versuchen, eines der fehlenden Module zu importieren, schlägt Python mit einem ModuleNotFoundError fehl.
Beispielsweise, nachdem sqlite-devel absichtlich vom lokalen System entfernt wurde
$ ./python -c "import sqlite3"
Traceback (most recent call last):
File "<string>", line 1, in <module>
File "/home/ncoghlan/devel/cpython/Lib/sqlite3/__init__.py", line 23, in <module>
from sqlite3.dbapi2 import *
File "/home/ncoghlan/devel/cpython/Lib/sqlite3/dbapi2.py", line 27, in <module>
from _sqlite3 import *
ModuleNotFoundError: No module named '_sqlite3'
Dies kann Benutzer verwirren, die möglicherweise nicht verstehen, warum ein sauber erstelltes Python Standardbibliothek-Module vermisst.
Linux und andere Distributionen
Viele Linux- und andere Distributionen trennen bereits Teile der Standardbibliothek in eigenständige Pakete. Zu den am häufigsten ausgeschlossenen Modulen gehören das tkinter-Modul, da es eine Abhängigkeit von der grafischen Umgebung mit sich bringt, idlelib, da es von tkinter abhängt (und die meisten Linux-Desktop-Umgebungen ihre eigene Standard-Code-Editor-Umgebung bereitstellen), und das test-Paket, da es nur zum internen Testen von Python dient und ungefähr so groß ist wie der Rest der Standardbibliothek zusammen.
Die Methoden, mit denen diese Module weggelassen werden, unterscheiden sich. Debian patched beispielsweise die Datei Lib/tkinter/__init__.py, um die Zeile import _tkinter in einen try-except-Block einzuschließen und fügt bei einem ImportError einfach Folgendes zur Fehlermeldung hinzu: please install the python3-tk package [1]. Fedora und andere Distributionen schließen die weggelassenen Module einfach nicht mit ein, was Benutzer möglicherweise ratlos macht, wo sie sie finden können.
Ein Beispiel von Fedora 29
$ python3 -c "import tkinter"
Traceback (most recent call last):
File "<string>", line 1, in <module>
ModuleNotFoundError: No module named 'tkinter'
Spezifikation
APIs zum Auflisten erwarteter Standardbibliothek-Module
Um eine einfachere Identifizierung zu ermöglichen, welche Modulnamen erwartet werden, in der Standardbibliothek aufgelöst zu werden, wird das Modul sysconfig um zwei zusätzliche Funktionen erweitert:
sysconfig.get_stdlib_modules(), die eine Liste der Namen aller Top-Level-Module der Python-Standardbibliothek (einschließlich privater Module) liefertsysconfig.get_optional_modules(), die optionale öffentliche Top-Level-Modulnamen der Standardbibliothek auflistet
Die Ergebnisse von sysconfig.get_optional_modules() und die vorhandenen sys.builtin_module_names sind beide Teilmengen der vollständigen Liste, die von der neuen Funktion sysconfig.get_stdlib_modules() bereitgestellt wird.
Diese hinzugefügten Listen werden während des Python-Build-Prozesses generiert und zusammen mit anderen sysconfig-Werten in der Datei _sysconfigdata-*.py gespeichert.
Mögliche Gründe für Module in der „optionalen“ Liste sind:
- das Modul beruht auf einer optionalen Build-Abhängigkeit (z. B.
_sqlite3,tkinter,idlelib) - das Modul ist aus anderen Gründen privat und daher möglicherweise nicht in allen Implementierungen vorhanden (z. B.
_freeze_importlib,_collections_abc) - das Modul ist plattformspezifisch und daher möglicherweise nicht in allen Installationen vorhanden (z. B.
winreg) - das
test-Paket kann ebenfalls frei von Python-Runtime-Installationen weggelassen werden, da es für das Testen von Python-Implementierungen bestimmt ist und keine Laufzeitbibliothek für Python-Projekte darstellt (die öffentliche API, die Test-Utilities anbietet, istunittest)
(Hinweis: Die Module ensurepip, venv und distutils werden in diesem PEP alle als zwingend erforderliche Module betrachtet, auch wenn nicht alle Weiterverteiler dies derzeit tun)
Änderungen an der Standard-sys.excepthook-Implementierung
Die Standardimplementierung der Funktion sys.excepthook wird dann modifiziert, um eine angemessene Nachricht auszugeben, wenn sie einen Fehler beim Import eines Moduls erkennt, das von einer der beiden neuen sysconfig-Funktionen als Teil der Python-Standardbibliothek identifiziert wurde.
Überarbeitete Fehlermeldung für ein Modul, das auf einer optionalen Build-Abhängigkeit beruht oder andernfalls als optional gilt, wenn Python installiert ist
$ ./python -c "import sqlite3"
Traceback (most recent call last):
File "<string>", line 1, in <module>
File "/home/ncoghlan/devel/cpython/Lib/sqlite3/__init__.py", line 23, in <module>
from sqlite3.dbapi2 import *
File "/home/ncoghlan/devel/cpython/Lib/sqlite3/dbapi2.py", line 27, in <module>
from _sqlite3 import *
ModuleNotFoundError: Optional standard library module '_sqlite3' was not found
Überarbeitete Fehlermeldung für ein Untermodul eines optionalen Top-Level-Pakets, wenn das gesamte Top-Level-Paket fehlt
$ ./python -c "import test.regrtest"
Traceback (most recent call last):
File "<string>", line 1, in <module>
ModuleNotFoundError: Optional standard library module 'test' was not found
Überarbeitete Fehlermeldung für ein Untermodul eines optionalen Top-Level-Pakets, wenn das Top-Level-Paket vorhanden ist
$ ./python -c "import test.regrtest"
Traceback (most recent call last):
File "<string>", line 1, in <module>
ModuleNotFoundError: No submodule named 'test.regrtest' in optional standard library module 'test'
Überarbeitete Fehlermeldung für ein Modul, das immer verfügbar sein soll
$ ./python -c "import ensurepip"
Traceback (most recent call last):
File "<string>", line 1, in <module>
ModuleNotFoundError: Standard library module 'ensurepip' was not found
Überarbeitete Fehlermeldung für ein fehlendes Untermodul eines Standardbibliothek-Pakets, wenn das Top-Level-Paket vorhanden ist
$ ./python -c "import encodings.mbcs"
Traceback (most recent call last):
File "<string>", line 1, in <module>
ModuleNotFoundError: No submodule named 'encodings.mbcs' in standard library module 'encodings'
Diese überarbeiteten Fehlermeldungen machen deutlich, dass die fehlenden Module voraussichtlich aus der Standardbibliothek verfügbar sein sollten, aber aus irgendeinem Grund nicht verfügbar sind, anstatt dass sie auf eine fehlende Abhängigkeit von Drittanbietern in der aktuellen Umgebung hinweisen.
Design-Diskussion
Modifikation von sys.excepthook
Die Funktion sys.excepthook wird aufgerufen, wenn eine ausgelöste Ausnahme unbehandelt bleibt und das Programm beendet wird oder (in einer interaktiven Sitzung) die Kontrolle an die Eingabeaufforderung zurückgegeben wird. Dies ist ein idealer Ort für benutzerdefinierte Fehlermeldungen, da sie keine gefangenen Fehler beeinflusst und somit die normale Ausführung von Python-Skripten nicht verlangsamt.
Öffentliche API zur Abfrage erwarteter Namen von Standardbibliothek-Modulen
Die Aufnahme der Funktionen sysconfig.get_stdlib_modules() und sysconfig.get_optional_modules() bietet eine seit langem gesuchte Möglichkeit, einfach die Namen von Python-Standardbibliothek-Modulen aufzulisten [2], was unter anderem dazu beiträgt, dass Code-Analyse-, Profiling- und Fehlerberichts-Tools Laufzeitoptionen wie --ignore-stdlib anbieten können.
Nur Namen von Top-Level-Modulen einschließen
Dieser PEP schlägt vor, dass nur Top-Level-Modul- und Paketnamen von den neuen Abfrage-APIs gemeldet werden. Dies sind ausreichende Informationen, um die vorgeschlagenen Fehlermeldungen zu generieren, reduziert die Anzahl der erforderlichen Einträge um eine Größenordnung und vereinfacht den Prozess der Generierung der zugehörigen Metadaten während des Build-Prozesses.
Wenn sich dies letztendlich als zu einschränkend herausstellt, könnte eine neue Flagge include_submodules zu den Abfrage-APIs hinzugefügt werden. Dies ist jedoch *nicht* Teil des ursprünglichen Vorschlags, da die Vorteile davon derzeit nicht die zusätzliche Komplexität rechtfertigen.
Eine bekannte Konsequenz dieser Einschränkung ist, dass die neue Standard-excepthook-Implementierung die Namen falscher Untermodule genauso meldet, wie sie tatsächlich fehlende Standardbibliothek-Untermodule meldet.
$ ./python -c "import unittest.muck"
Traceback (most recent call last):
File "<string>", line 1, in <module>
ModuleNotFoundError: No submodule named 'unittest.muck' in standard library module 'unittest'
Auflisten privater Top-Level-Modulnamen als optionale Standardbibliothek-Module
Viele der Module, die eine optionale externe Build-Abhängigkeit haben, sind als Hybridmodule geschrieben, bei denen ein gemeinsamer Python-Wrapper um eine implementierungsabhängige Schnittstelle zur zugrunde liegenden externen Bibliothek liegt. In anderen Fällen kann ein privates Top-Level-Modul einfach ein CPython-Implementierungsdetail sein, und andere Implementierungen bieten dieses Modul möglicherweise gar nicht an.
Um Importfehler mit diesen Modulen angemessen zu melden, benötigt die neue Standard-excepthook-Implementierung, dass sie von den neuen Abfrage-APIs gemeldet werden.
Zurückgestellte Ideen
Die Ideen in diesem Abschnitt sind Konzepte, die dieser PEP potenziell ermöglichen würde, sie werden jedoch für den ursprünglichen Vorschlag als nicht im Geltungsbereich betrachtet.
Plattformabhängige Module
Einige Standardbibliothek-Module können fehlen, weil sie nur auf bestimmten Plattformen verfügbar sind. Zum Beispiel ist das Modul winreg nur unter Windows verfügbar.
$ python3 -c "import winreg"
Traceback (most recent call last):
File "<string>", line 1, in <module>
ModuleNotFoundError: No module named 'winreg'
Im aktuellen Vorschlag werden diese plattformabhängigen Module einfach mit allen anderen optionalen Modulen zusammengeführt, anstatt zu versuchen, die Plattformabhängigkeitsinformationen strukturierter darzustellen.
Die Plattformabhängigkeit wird jedoch zumindest auf der Ebene von „Windows“, „Unix“, „Linux“ und „FreeBSD“ für die Dokumentation verfolgt, so dass es plausibel erscheint, dass sie auch programmatisch ausgestellt werden könnte.
Ausgabe einer Warnung, wenn __main__ ein Standardbibliothek-Modul überschattet
Angesichts der neuen Abfrage-APIs könnte die neue Standard-excepthook-Implementierung potenziell erkennen, wenn __main__.__file__ oder __main__.__spec__.name mit einem Standardbibliothek-Modul übereinstimmen, und eine entsprechende Warnung ausgeben.
Alles in dieser Richtung sollte jedoch gründlich geprüft werden, da die Anwender dieses Problem tatsächlich erfahren und verschiedene Optionen existieren, um mehr Informationen zur Fehlersuche anzubieten, anstatt es sofort einbauen zu müssen.
Empfehlung für nachgelagerte Distributoren
Indem sie site.py [*] patchen, um ihre eigene Implementierung der Funktion sys.excepthook bereitzustellen, können Python-Distributoren maßgeschneiderte Fehlermeldungen für alle unbehandelten Ausnahmen anzeigen, einschließlich der Benachrichtigung des Benutzers über eine geeignete, distro-spezifische Methode zur Installation fehlender Standardbibliothek-Module bei einem ModuleNotFoundError.
Einige nachgelagerte Distributoren verwenden diese Methode bereits, indem sie sys.excepthook patchen, um mit plattformspezifischen Absturzberichtmechanismen zu integrieren.
Abwärtskompatibilität
Es werden keine Probleme mit der Abwärtskompatibilität erwartet. Distributionen, die bereits Python-Module patchen, um eine benutzerdefinierte Handhabung fehlender Abhängigkeiten bereitzustellen, können dies ungehindert fortsetzen.
Referenz und Beispielimplementierung
TBD. Die feineren Details hängen davon ab, was angesichts der Fähigkeiten des CPython-Build-Systems praktisch ist (andere Implementierungen sollten dann die generierten CPython-Daten verwenden können, anstatt sie selbst neu generieren zu müssen).
Hinweise und Referenzen
Ideen, die zu diesem PEP führten, wurden auf der python-dev Mailingliste und anschließend auf python-ideas diskutiert.
Urheberrecht
Dieses Dokument wurde gemeinfrei erklärt.
Quelle: https://github.com/python/peps/blob/main/peps/pep-0534.rst
Zuletzt geändert: 2025-02-01 08:55:40 GMT