PEP 514 – Python-Registrierung in der Windows-Registrierung
- Autor:
- Steve Dower <steve.dower at python.org>
- BDFL-Delegate:
- Paul Moore <p.f.moore at gmail.com>
- Status:
- Aktiv
- Typ:
- Informational
- Erstellt:
- 02-Feb-2016
- Post-History:
- 02-Feb-2016, 01-Mar-2016, 18-Jul-2016
- Resolution:
- Python-Dev Nachricht
Zusammenfassung
Dieses PEP definiert ein Schema für den Registrierungsschlüssel von Python, damit Drittanbieter-Installationsprogramme ihre Installation registrieren können und Tools und Anwendungen alle Python-Umgebungen auf dem Computer eines Benutzers erkennen und korrekt anzeigen können. Mit diesem PEP werden keine Implementierungsänderungen an Python vorgeschlagen.
Python-Umgebungen müssen nicht registriert werden, es sei denn, sie sollen von externen Tools automatisch erkannt werden. Da dies nur Windows betrifft, sind diese Tools voraussichtlich überwiegend grafische Benutzeroberflächen. Konsolenanwendungen können die registrierten Informationen jedoch auch nutzen. Dieses PEP behandelt die Informationen, die verfügbar gemacht werden können, die eigentliche Darstellung und Verwendung dieser Informationen liegt jedoch bei den Tool-Entwicklern.
Das Schema entspricht den Registrierungswerten, die seit mindestens Python 2.5 vom offiziellen Installer verwendet werden, und das Auflösungsverhalten entspricht dem Verhalten der offiziellen Python-Releases. Es werden einige Regeln zur Abwärtskompatibilität bereitgestellt, um sicherzustellen, dass Tools Versionen von CPython korrekt erkennen können, die keine vollständigen Informationen registrieren.
Motivation
Wenn der offizielle Python-Installer unter Windows installiert wird, erstellt er einen Registrierungsschlüssel zur Erkennung durch andere Anwendungen. Dies ermöglicht es Tools wie Installationsprogrammen oder IDEs, die Python-Installationen eines Benutzers automatisch zu erkennen und anzuzeigen. Zum Beispiel nutzt der PEP 397 py.exe Launcher und Editoren wie PyCharm und Visual Studio bereits diese Informationen.
Drittanbieter-Installationsprogramme, wie sie von Distributionen verwendet werden, erstellen in der Regel identische Schlüssel für denselben Zweck. Die meisten Tools, die die Registrierung zur Erkennung von Python-Installationen verwenden, untersuchen nur die vom offiziellen Installer verwendeten Schlüssel. Daher überschreiben Drittanbieter-Installationen, die erkannt werden sollen, diese Werte und führen oft dazu, dass Benutzer ihre ursprüngliche Python-Installation "verlieren".
Durch die Beschreibung eines Layouts für Registrierungsschlüssel, das es Drittanbieter-Installationen ermöglicht, sich eindeutig zu registrieren, und durch die Bereitstellung von Anleitungen für Tool-Entwickler zur Erkennung aller verfügbaren Python-Installationen sollten diese Kollisionen verhindert werden. Wir nutzen auch die Gelegenheit, einige bekannte Metadaten hinzuzufügen, damit mehr Informationen für Benutzer angezeigt werden können.
Definitionen
Ein "Registrierungsschlüssel" ist das Äquivalent eines Dateisystempfads in der Registrierung. Jeder Schlüssel kann "Unterschlüssel" (Schlüssel, die in Schlüsseln verschachtelt sind) und "Werte" (benannte und typisierte Attribute, die einem Schlüssel zugeordnet sind) enthalten. Diese werden unter Windows verwendet, um Einstellungen auf die gleiche Weise zu speichern, wie Verzeichnisse mit Konfigurationsdateien funktionieren würden.
HKEY_CURRENT_USER ist die Wurzel der Einstellungen für den aktuell angemeldeten Benutzer, und dieser Benutzer kann alle Einstellungen unter dieser Wurzel im Allgemeinen lesen und schreiben.
HKEY_LOCAL_MACHINE ist die Wurzel der Einstellungen für alle Benutzer. Im Allgemeinen kann jeder Benutzer diese Einstellungen lesen, aber nur Administratoren können sie ändern. Es ist üblich, dass Werte unter HKEY_CURRENT_USER Vorrang vor denen in HKEY_LOCAL_MACHINE haben.
Auf 64-Bit-Windows ist HKEY_LOCAL_MACHINE\Software\Wow6432Node ein spezieller Schlüssel, zu dem 32-Bit-Prozesse transparent lesen und schreiben, anstatt direkt auf den Software-Schlüssel zuzugreifen.
Weitere Dokumentation zur Registrierungsweiterleitung unter Windows ist in der MSDN Library [1] verfügbar.
Struktur
Wir betrachten eine einzige Sammlung von Python-Umgebungen auf einem Computer, wobei die Sammlung für jeden Benutzer des Computers unterschiedlich sein kann. Es gibt drei potenzielle Registrierungsorte, an denen die Sammlung basierend auf den Installationsoptionen jeder Umgebung gespeichert werden kann.
HKEY_CURRENT_USER\Software\Python\<Company>\<Tag>
HKEY_LOCAL_MACHINE\Software\Python\<Company>\<Tag>
HKEY_LOCAL_MACHINE\Software\Wow6432Node\Python\<Company>\<Tag>
Offizielle Python-Releases verwenden PythonCore für Firma und den Wert von sys.winver für Tag. Die Firma PyLauncher ist reserviert. Andere registrierte Umgebungen können beliebige Werte für Firma und Tag verwenden. Empfehlungen werden später in diesem Dokument gegeben.
Firmen-Tag-Paare sind Groß-/Kleinschreibung-unabhängig und identifizieren jede Umgebung eindeutig. Abhängig vom Zweck und der beabsichtigten Verwendung eines Tools gibt es zwei vorgeschlagene Ansätze zur Auflösung von Konflikten zwischen Firmen-Tag-Paaren.
Tools, die jede installierte Umgebung auflisten, können diese auch dann einschließen, wenn die Firmen-Tag-Paare übereinstimmen. Sie sollten sicherstellen, dass Benutzer leicht erkennen können, ob die Registrierung pro Benutzer oder pro Maschine erfolgte und welche Registrierung Vorrang hat.
Tools, die eine einzelne installierte Umgebung aus allen registrierten Umgebungen basierend auf dem Firmen-Tag-Paar auswählen sollen, wie z. B. der py.exe Launcher, sollten immer die in HKEY_CURRENT_USER registrierte Umgebung auswählen, wenn die übereinstimmende in HKEY_LOCAL_MACHINE vorhanden ist.
Konflikte zwischen HKEY_LOCAL_MACHINE\Software\Python und HKEY_LOCAL_MACHINE\Software\Wow6432Node\Python sollten nur auftreten, wenn sowohl 64-Bit- als auch 32-Bit-Versionen eines Interpreters denselben Tag haben. In diesem Fall sollte das Tool das auswählen, was für seine Verwendung geeigneter ist.
Wenn ein Tool anhand der bereitgestellten Informationen (oder deren Fehlen) feststellen kann, dass es eine registrierte Umgebung nicht verwenden kann, besteht keine Verpflichtung, diese den Benutzern anzuzeigen.
Mit Ausnahme der im Abschnitt zur Abwärtskompatibilität beschriebenen Fälle werden Firmen- und Tag-Werte von Tools als undurchsichtig betrachtet, und es sollten keine Informationen über den Interpreter aus dem Text abgeleitet werden. Einige Tools können jedoch die Firmen- und Tag-Werte für Benutzer anzeigen, daher sollte der Tag idealerweise den Benutzern helfen, die zugehörige Umgebung zu identifizieren.
Python-Umgebungen müssen sich nicht selbst registrieren, es sei denn, sie sollen von externen Tools automatisch erkannt werden.
Abwärtskompatibilität
Python 3.4 und früher unterschieden in sys.winver nicht zwischen 32-Bit- und 64-Bit-Builds. Daher ist es nicht möglich, gültige Side-by-Side-Installationen sowohl von 32-Bit- als auch von 64-Bit-Interpretern unter diesem Schema zu haben, da dies zu doppelten Tags führen würde.
Um die Abwärtskompatibilität zu gewährleisten, sollten Anwendungen Umgebungen, die unter den folgenden beiden Registrierungsschlüsseln aufgeführt sind, als unterschiedlich behandeln, auch wenn der Tag übereinstimmt.
HKEY_LOCAL_MACHINE\Software\Python\PythonCore\<Tag>
HKEY_LOCAL_MACHINE\Software\Wow6432Node\Python\PythonCore\<Tag>
Umgebungen, die unter HKEY_CURRENT_USER aufgeführt sind, können als unterschiedlich von beiden obigen Schlüsseln behandelt werden, was potenziell zu drei Umgebungen führt, die mit demselben Tag erkannt werden. Alternativ kann ein Tool feststellen, ob die pro Benutzer-Umgebung 64-Bit oder 32-Bit ist, und ihr Vorrang vor der pro Maschine-Umgebung geben, was zu maximal zwei erkannten Umgebungen führt.
Es ist nicht möglich, Side-by-Side-Installationen von 64-Bit- und 32-Bit-Versionen von Python vor Version 3.5 zu erkennen, wenn sie für den aktuellen Benutzer installiert wurden. Python 3.5 und neuere Versionen verwenden immer unterschiedliche Tags für 64-Bit- und 32-Bit-Versionen.
Der folgende Abschnitt beschreibt benutzerbezogene Informationen, die registriert werden können. Für Python 3.5 und älter sind keine dieser Informationen verfügbar, aber für den PythonCore-Schlüssel werden alternative Standardwerte angegeben.
Umgebungen, die unter anderen Firmennamen registriert sind, haben keine Anforderungen an die Abwärtskompatibilität und müssen eindeutige Tags verwenden, um Side-by-Side-Installationen zu unterstützen. Tools, die diese Registrierungen nutzen, müssen Tags nicht anders als durch die Bevorzugung der Benutzereinstellung disambiguieren.
Firma
Der Firmenbestandteil des Schlüssels dient dazu, verwandte Umgebungen zu gruppieren und sicherzustellen, dass Tags ordnungsgemäß benannt sind. Der Schlüsselname sollte alphanumerisch ohne Leerzeichen sein und wahrscheinlich eindeutig. Zum Beispiel wäre ein eingetragener Name (bevorzugt), ein Hostname oder als letztes Mittel eine UUID geeignet.
HKEY_CURRENT_USER\Software\Python\ExampleCorp
HKEY_CURRENT_USER\Software\Python\www.example.com
HKEY_CURRENT_USER\Software\Python\6C465E66-5A8C-4942-9E6A-D29159480C60
Der Firmenname PyLauncher ist für den PEP 397 Launcher (py.exe) reserviert. Er folgt nicht dieser Konvention und sollte von Tools ignoriert werden.
Wenn ein Zeichenkettenwert namens DisplayName existiert, sollte er verwendet werden, um den Hersteller/Entwickler/Vertreiber der Umgebung für Benutzer zu identifizieren. Andernfalls sollte der Name des Schlüssels verwendet werden. (Für PythonCore ist der Standardanzeigename "Python Software Foundation".)
Wenn ein Zeichenkettenwert namens SupportUrl existiert, kann er angezeigt oder anderweitig verwendet werden, um Benutzer zu einer Website zu leiten, die sich auf die Umgebung bezieht. (Für PythonCore ist die Standard-Support-URL "https://pythonlang.de/".)
Ein vollständiges Beispiel könnte so aussehen:
HKEY_CURRENT_USER\Software\Python\ExampleCorp
(Default) = (value not set)
DisplayName = "Example Corp"
SupportUrl = "http://www.example.com"
Tag
Der Tag-Teil des Schlüssels dient dazu, eine Umgebung innerhalb der von einer einzelnen Firma bereitgestellten Umgebungen eindeutig zu identifizieren. Der Schlüsselname sollte alphanumerisch ohne Leerzeichen sein und bei Installationen stabil bleiben. Zum Beispiel wären die Python-Sprachversion, eine UUID oder ein teilweiser/vollständiger Hash geeignet, während ein Tag, der auf dem Installationsverzeichnis oder einem Aspekt des aktuellen Rechners basiert, möglicherweise nicht geeignet ist. Zum Beispiel:
HKEY_CURRENT_USER\Software\Python\ExampleCorp\examplepy
HKEY_CURRENT_USER\Software\Python\ExampleCorp\3.6
HKEY_CURRENT_USER\Software\Python\ExampleCorp\6C465E66
Es wird erwartet, dass einige Tools von Benutzern verlangen, den Tag in eine Befehlszeile einzugeben, und dass die Firma optional sein kann, vorausgesetzt, der Tag ist eindeutig für alle Python-Installationen. Kurze, menschenlesbare und leicht zu tippende Tags werden empfohlen, und wenn möglich, wählen Sie einen Wert, der wahrscheinlich eindeutig für alle anderen Firmen ist.
Wenn ein Zeichenkettenwert namens DisplayName existiert, sollte er verwendet werden, um die Umgebung für Benutzer zu identifizieren. Andernfalls sollte der Name des Schlüssels verwendet werden. (Für PythonCore ist der Standard "Python " gefolgt vom Tag.)
Wenn ein Zeichenkettenwert namens SupportUrl existiert, kann er angezeigt oder anderweitig verwendet werden, um Benutzer zu einer Website zu leiten, die sich auf die Umgebung bezieht. (Für PythonCore ist der Standard "https://pythonlang.de/".)
Wenn ein Zeichenkettenwert namens Version existiert, sollte er verwendet werden, um die Version der Umgebung zu identifizieren. Diese ist unabhängig von der von der Umgebung implementierten Python-Version. (Für PythonCore ist der Standard die ersten drei Zeichen des Tags.)
Wenn ein Zeichenkettenwert namens SysVersion existiert, muss er im Format x.y oder x.y.z vorliegen und der von sys.version_info im Interpreter zurückgegebenen Version entsprechen. Wenn weggelassen, ist die Python-Version unbekannt. (Für PythonCore ist der Standard die ersten drei Zeichen des Tags.)
Wenn ein Zeichenkettenwert namens SysArchitecture existiert, muss er dem ersten Element des von platform.architecture() zurückgegebenen Tupels entsprechen. Typischerweise ist dies "32bit" oder "64bit". Wenn weggelassen, ist die Architektur unbekannt. (Für PythonCore ist die Architektur "32bit", wenn unter HKEY_LOCAL_MACHINE\Software\Wow6432Node\Python oder überall auf einem 32-Bit-Betriebssystem registriert, "64bit", wenn unter HKEY_LOCAL_MACHINE\Software\Python auf einem 64-Bit-Computer registriert, und unbekannt, wenn unter HKEY_CURRENT_USER registriert.)
Beachten Sie, dass jeder dieser Werte empfohlen, aber optional ist. Das Weglassen von SysVersion oder SysArchitecture kann dazu führen, dass einige Tools die Umgebung nicht korrekt unterstützen. Ein vollständiges Beispiel könnte so aussehen:
HKEY_CURRENT_USER\Software\Python\ExampleCorp\examplepy
(Default) = (value not set)
DisplayName = "Example Py Distro 3"
SupportUrl = "http://www.example.com/distro-3"
Version = "3.0.12345.0"
SysVersion = "3.6.0"
SysArchitecture = "64bit"
Installationspfad
Unter dem Umgebungsschlüssel muss ein InstallPath-Schlüssel erstellt werden. Dieser Schlüssel wird immer InstallPath genannt, und der Standardwert muss sys.prefix entsprechen.
HKEY_CURRENT_USER\Software\Python\ExampleCorp\3.6\InstallPath
(Default) = "C:\ExampleCorpPy36"
Wenn ein Zeichenkettenwert namens ExecutablePath existiert, muss dies der vollständige Pfad zur python.exe (oder einem Äquivalent) sein. Wenn weggelassen, ist die Umgebung nicht ausführbar. (Für PythonCore ist der Standard die Datei python.exe im Verzeichnis, auf das der Wert (Default) verweist.)
Wenn ein Zeichenkettenwert namens ExecutableArguments existiert, sollten Tools den Wert als erste Argumente beim Ausführen von ExecutablePath verwenden. Tools können weitere Argumente nach diesen hinzufügen und werden vernünftigerweise erwarten, dass Standard-Python-Befehlszeilenoptionen verfügbar sind.
Wenn ein Zeichenkettenwert namens WindowedExecutablePath existiert, muss dies ein Pfad zur pythonw.exe (oder einem Äquivalent) sein. Wenn weggelassen, ist der Standardwert der Wert von ExecutablePath, und wenn dieser weggelassen wird, ist die Umgebung nicht ausführbar. (Für PythonCore ist der Standard die Datei pythonw.exe im Verzeichnis, auf das der Wert (Default) verweist.)
Wenn ein Zeichenkettenwert namens WindowedExecutableArguments existiert, sollten Tools den Wert als erste Argumente beim Ausführen von WindowedExecutablePath verwenden. Tools können weitere Argumente nach diesen hinzufügen und werden vernünftigerweise erwarten, dass Standard-Python-Befehlszeilenoptionen verfügbar sind.
Ein vollständiges Beispiel könnte so aussehen:
HKEY_CURRENT_USER\Software\Python\ExampleCorp\examplepy\InstallPath
(Default) = "C:\ExampleDistro30"
ExecutablePath = "C:\ExampleDistro30\ex_python.exe"
ExecutableArguments = "--arg1"
WindowedExecutablePath = "C:\ExampleDistro30\ex_pythonw.exe"
WindowedExecutableArguments = "--arg1"
Hilfe
Unter dem Umgebungsschlüssel kann ein Help-Schlüssel erstellt werden. Dieser Schlüssel wird, falls vorhanden, immer Help genannt und hat keinen Standardwert.
Jeder Unterschlüssel von Help gibt eine Dokumentationsdatei, ein Tool oder eine URL an, die mit der Umgebung verbunden ist. Der Unterschlüssel kann jeden Namen haben, und der Standardwert ist eine Zeichenkette, die für die Übergabe an os.startfile oder ein Äquivalent geeignet ist.
Wenn ein Zeichenkettenwert namens DisplayName existiert, sollte er verwendet werden, um die Hilfedatei für Benutzer zu identifizieren. Andernfalls sollte der Schlüsselname verwendet werden.
Ein vollständiges Beispiel könnte so aussehen:
HKEY_CURRENT_USER\Software\Python\ExampleCorp\6C465E66\Help
Python\
(Default) = "C:\ExampleDistro30\python36.chm"
DisplayName = "Python Documentation"
Extras\
(Default) = "http://www.example.com/tutorial"
DisplayName = "Example Distro Online Tutorial"
Andere Schlüssel
Alle anderen Unterschlüssel unter einem Firmen-Tag-Paar stehen zur privaten Nutzung zur Verfügung.
Offizielle CPython-Releases haben traditionell bestimmte Schlüssel in diesem Bereich verwendet, um den Speicherort der Python-Standardbibliothek und anderer installierter Module zu bestimmen. Dieses Verhalten wird hauptsächlich aus Gründen der Abwärtskompatibilität beibehalten. Da der Code, der diese Werte liest, jedoch in den Interpreter eingebettet ist, können Drittanbieter-Distributionen von Werten, die in PythonCore geschrieben werden, wenn ein unveränderter Interpreter verwendet wird, betroffen sein.
Beispielcode
Dieser Beispielcode zählt die Registrierung auf und zeigt die verfügbaren Firmen-Tag-Paare an, die zum Starten einer Umgebung verwendet werden könnten, sowie die Ziel-Executable. Er zeigt nur das am meisten bevorzugte Ziel für den Tag an. Die abwärtskompatible Handhabung von PythonCore ist ausgelassen, wird aber in einem späteren Beispiel gezeigt.
# Display most-preferred environments.
# Assumes a 64-bit operating system
# Does not correctly handle PythonCore compatibility
import winreg
def enum_keys(key):
i = 0
while True:
try:
yield winreg.EnumKey(key, i)
except OSError:
break
i += 1
def get_value(key, value_name):
try:
return winreg.QueryValue(key, value_name)
except FileNotFoundError:
return None
seen = set()
for hive, key, flags in [
(winreg.HKEY_CURRENT_USER, r'Software\Python', 0),
(winreg.HKEY_LOCAL_MACHINE, r'Software\Python', winreg.KEY_WOW64_64KEY),
(winreg.HKEY_LOCAL_MACHINE, r'Software\Python', winreg.KEY_WOW64_32KEY),
]:
with winreg.OpenKeyEx(hive, key, access=winreg.KEY_READ | flags) as root_key:
for company in enum_keys(root_key):
if company == 'PyLauncher':
continue
with winreg.OpenKey(root_key, company) as company_key:
for tag in enum_keys(company_key):
if (company, tag) in seen:
if company == 'PythonCore':
# TODO: Backwards compatibility handling
pass
continue
seen.add((company, tag))
try:
with winreg.OpenKey(company_key, tag + r'\InstallPath') as ip_key:
exec_path = get_value(ip_key, 'ExecutablePath')
exec_args = get_value(ip_key, 'ExecutableArguments')
if company == 'PythonCore' and not exec_path:
# TODO: Backwards compatibility handling
pass
except OSError:
exec_path, exec_args = None, None
if exec_path:
print('{}\\{} - {} {}'.format(company, tag, exec_path, exec_args or ''))
else:
print('{}\\{} - (not executable)'.format(company, tag))
Dieses Beispiel scannt nur PythonCore-Einträge für den aktuellen Benutzer. Wo Daten fehlen, werden die oben im PEP beschriebenen Standardwerte eingesetzt. Beachten Sie, dass diese Standardwerte nur unter PythonCore verwendet werden; andere Registrierungen haben keine Standardwerte.
# Only lists per-user PythonCore registrations
# Uses fallback values as described in PEP 514
import os
import winreg
def enum_keys(key):
i = 0
while True:
try:
yield winreg.EnumKey(key, i)
except OSError:
break
i += 1
def get_value(key, value_name):
try:
return winreg.QueryValue(key, value_name)
except FileNotFoundError:
return None
with winreg.OpenKey(winreg.HKEY_CURRENT_USER, r"Software\Python\PythonCore") as company_key:
print('Company:', get_value(company_key, 'DisplayName') or 'Python Software Foundation')
print('Support:', get_value(company_key, 'SupportUrl') or 'https://pythonlang.de/')
print()
for tag in enum_keys(company_key):
with winreg.OpenKey(company_key, tag) as tag_key:
print('PythonCore\\' + tag)
print('Name:', get_value(tag_key, 'DisplayName') or ('Python ' + tag))
print('Support:', get_value(tag_key, 'SupportUrl') or 'https://pythonlang.de/')
print('Version:', get_value(tag_key, 'Version') or tag[:3])
print('SysVersion:', get_value(tag_key, 'SysVersion') or tag[:3])
# Architecture is unknown because we are in HKCU
# Tools may use alternate approaches to determine architecture when
# the registration does not specify it.
print('SysArchitecture:', get_value(tag_key, 'SysArchitecture') or '(unknown)')
try:
ip_key = winreg.OpenKey(company_key, tag + '\\InstallPath')
except FileNotFoundError:
pass
else:
with ip_key:
ip = get_value(ip_key, None)
exe = get_value(ip_key, 'ExecutablePath') or os.path.join(ip, 'python.exe')
exew = get_value(ip_key, 'WindowedExecutablePath') or os.path.join(ip, 'python.exe')
print('InstallPath:', ip)
print('ExecutablePath:', exe)
print('WindowedExecutablePath:', exew)
print()
Dieses Beispiel zeigt einen Teil der Registrierung, die von einer Nur-für-mich-Installation von 64-Bit Python 3.6.0 erstellt wird. Es können auch andere Schlüssel erstellt werden.
HKEY_CURRENT_USER\Software\Python\PythonCore
(Default) = (value not set)
DisplayName = "Python Software Foundation"
SupportUrl = "https://pythonlang.de/"
HKEY_CURRENT_USER\Software\Python\PythonCore\3.6
(Default) = (value not set)
DisplayName = "Python 3.6 (64-bit)"
SupportUrl = "https://pythonlang.de/"
Version = "3.6.0"
SysVersion = "3.6"
SysArchitecture = "64bit"
HKEY_CURRENT_USER\Software\Python\PythonCore\3.6\Help\Main Python Documentation
(Default) = "C:\Users\Me\AppData\Local\Programs\Python\Python36\Doc\python360.chm"
DisplayName = "Python 3.6.0 Documentation"
HKEY_CURRENT_USER\Software\Python\PythonCore\3.6\InstallPath
(Default) = "C:\Users\Me\AppData\Local\Programs\Python\Python36\"
ExecutablePath = "C:\Users\Me\AppData\Local\Programs\Python\Python36\python.exe"
WindowedExecutablePath = "C:\Users\Me\AppData\Local\Programs\Python\Python36\pythonw.exe"
Referenzen
Urheberrecht
Dieses Dokument wurde gemeinfrei erklärt.
Quelle: https://github.com/python/peps/blob/main/peps/pep-0514.rst
Zuletzt geändert: 2025-02-01 08:59:27 GMT