PEP 389 – argparse - Neues Modul zur Verarbeitung von Kommandozeilenargumenten
- Autor:
- Steven Bethard <steven.bethard at gmail.com>
- Status:
- Final
- Typ:
- Standards Track
- Erstellt:
- 25-Sep-2009
- Python-Version:
- 2.7, 3.2
- Post-History:
- 27-Sep-2009, 24-Oct-2009
Inhaltsverzeichnis
- Akzeptanz
- Zusammenfassung
- Motivation
- Warum reichen getopt und optparse nicht aus?
- Warum wird die Funktionalität nicht einfach zu optparse hinzugefügt?
- Veraltung von optparse
- Aktualisierungen der getopt-Dokumentation
- Zurückgestellt: String-Formatierung
- Abgelehnt: getopt-Kompatibilitätsmethoden
- Außerhalb des Rahmens: Verschiedene Funktionsanfragen
- Diskussion: sys.stderr und sys.exit
- Referenzen
- Urheberrecht
Akzeptanz
Dieser PEP wurde von Guido am 21. Februar 2010 in python-dev genehmigt [17].
Zusammenfassung
Dieser PEP schlägt die Aufnahme des argparse-Moduls [1] in die Python-Standardbibliothek in Python 2.7 und 3.2 vor.
Motivation
Das argparse-Modul ist eine Bibliothek zur Verarbeitung von Kommandozeilenargumenten, die mehr Funktionalität bietet als die bestehenden Module zur Verarbeitung von Kommandozeilenargumenten in der Standardbibliothek, getopt [2] und optparse [3]. Es unterstützt positionelle Argumente (nicht nur Optionen), Unterbefehle, erforderliche Optionen, Optionssyntaxen wie „/f“ und „+rgb“, Argumente im Stil von null oder mehr und eins oder mehr und viele andere Funktionen, die den beiden anderen fehlen.
Das argparse-Modul ist auch bereits ein beliebter Drittanbieter-Ersatz für diese Module. Es wird in Projekten wie IPython (der Scipy Python Shell) [4] verwendet, ist in Debian testing und unstable enthalten [5] und es gab seit 2007 verschiedene Anfragen zur Aufnahme in die Standardbibliothek [6] [7] [8]. Diese Beliebtheit deutet darauf hin, dass es eine wertvolle Ergänzung für die Python-Bibliotheken sein könnte.
Warum reichen getopt und optparse nicht aus?
Ein Argument gegen die Aufnahme von argparse ist, dass es „bereits zwei verschiedene Module zur Optionsverarbeitung in der Standardbibliothek gibt“ [9]. Im Folgenden sind die Funktionen aufgeführt, die argparse bietet, aber nicht in getopt oder optparse vorhanden sind.
- Während es stimmt, dass es zwei Bibliotheken zur *Optionsverarbeitung* gibt, gibt es keine vollständigen Bibliotheken zur Verarbeitung von Kommandozeilenargumenten – sowohl getopt als auch optparse unterstützen nur Optionen und keine positionellen Argumente. Das argparse-Modul behandelt beides und kann daher bessere Hilfetexte generieren, wodurch Redundanzen wie der von optparse normalerweise erforderliche „usage=“-String vermieden werden.
- Das argparse-Modul legt Wert auf Praktikabilität gegenüber Reinheit. Daher erlaubt argparse erforderliche Optionen und die Anpassung der Zeichen, die zur Identifizierung von Optionen verwendet werden, während optparse ausdrücklich besagt, dass „der Begriff 'erforderliche Option' widersprüchlich ist“ und dass die Optionssyntaxen
-pf,-file,+f,+rgb,/fund/file„nicht von optparse unterstützt werden und niemals unterstützt werden“. - Das argparse-Modul erlaubt Optionen, eine variable Anzahl von Argumenten mit
nargs='?',nargs='*'odernargs='+'zu akzeptieren. Das optparse-Modul bietet ein nicht getestetes Rezept für einen Teil dieser Funktionalität [10], gibt aber zu, dass „die Dinge schwierig werden, wenn man möchte, dass eine Option eine variable Anzahl von Argumenten annimmt.“ - Das argparse-Modul unterstützt Unterbefehle, bei denen ein Hauptparser für Kommandozeilenargumente je nach Kommandozeilenargumenten zu anderen Parsern für Kommandozeilenargumente weiterleitet. Dies ist ein gängiges Muster in Kommandozeilenoberflächen, z.B.
svn coundsvn up.
Warum wird die Funktionalität nicht einfach zu optparse hinzugefügt?
Offensichtlich bieten alle oben genannten Funktionen Verbesserungen gegenüber dem, was durch optparse verfügbar ist. Eine vernünftige Frage ist dann, warum diese Funktionen nicht einfach als Patches für optparse bereitgestellt werden, anstatt ein völlig neues Modul einzuführen. Tatsächlich war die ursprüngliche Entwicklung von argparse genau dazu gedacht, aber aufgrund verschiedener ziemlich einschränkender Designentscheidungen von optparse war dies nicht wirklich möglich. Einige der Probleme umfassten
- Das optparse-Modul legt die Interna seines Parsing-Algorithmus offen. Insbesondere
parser.largsundparser.rargsstehen für Callbacks garantiert zur Verfügung [11]. Dies macht es extrem schwierig, den Parsing-Algorithmus zu verbessern, wie es in argparse für die korrekte Verarbeitung von positionellen Argumenten und Argumenten variabler Länge notwendig war. Zum Beispiel wirdnargs='+'in argparse mithilfe von regulären Ausdrücken abgeglichen und hat daher keine Vorstellung von Dingen wieparser.largs. - Die optparse-Erweiterungs-APIs sind extrem komplex. Zum Beispiel müssen Sie, um nur eine einfache benutzerdefinierte Zeichenketten-zu-Objekt-Konvertierungsfunktion zu verwenden, von
Optionableiten, Klassenattribute hacken und dann Ihren benutzerdefinierten Optionstyp für den Parser angeben, wie folgt:class MyOption(Option): TYPES = Option.TYPES + ("mytype",) TYPE_CHECKER = copy(Option.TYPE_CHECKER) TYPE_CHECKER["mytype"] = check_mytype parser = optparse.OptionParser(option_class=MyOption) parser.add_option("-m", type="mytype")
Zum Vergleich: argparse erlaubt einfach die Verwendung von Konvertierungsfunktionen als
type=-Argumente direkt, z.B.:parser = argparse.ArgumentParser() parser.add_option("-m", type=check_mytype)
Angesichts der barocken Anpassungs-APIs von optparse ist jedoch unklar, wie sich eine solche Funktion mit diesen APIs interagieren sollte, und es ist sehr gut möglich, dass die Einführung der einfachen argparse-API bestehenden benutzerdefinierten Option-Code brechen würde.
- Sowohl optparse als auch argparse parsen Kommandozeilenargumente und weisen sie als Attribute einem Objekt zu, das von
parse_argszurückgegeben wird. Das optparse-Modul garantiert jedoch, dass dertake_action-Methode benutzerdefinierter Aktionen immer einvalues-Objekt übergeben wird, das eineensure_value-Methode bereitstellt [12], während das argparse-Modul erlaubt, Attribute an beliebige Objekte zuzuweisen, z.B.:foo_object = ... parser.parse_args(namespace=foo_object) foo_object.some_attribute_parsed_from_command_line
Das Modifizieren von optparse, um beliebige Objekte übergeben zu lassen, wäre schwierig, da das einfache Übergeben des
foo_objectanstelle einerValues-Instanz bestehende benutzerdefinierte Aktionen, die von derensure_value-Methode abhängen, unterbrechen würde.
Aufgrund solcher Probleme, die es argparse übermäßig schwierig machten, mit den optparse-APIs kompatibel zu bleiben, wurde argparse als unabhängiges Modul entwickelt. Angesichts dieser Probleme erscheint das Zusammenführen aller argparse-Funktionen in optparse ohne Rückwärtskompatibilitätsprobleme unwahrscheinlich.
Veraltung von optparse
Da alle Funktionen von optparse in argparse verfügbar sind, wird das optparse-Modul veraltet sein. Aufgrund der weit verbreiteten Nutzung von optparse enthält die Strategie zur Veraltung jedoch nur Dokumentationsänderungen und Warnungen, die standardmäßig nicht sichtbar sind.
- Python 2.7+ und 3.2+ – Die folgende Notiz wird der optparse-Dokumentation hinzugefügt.Das optparse-Modul ist veraltet und wird nicht weiterentwickelt; die Weiterentwicklung erfolgt mit dem argparse-Modul.
- Python 2.7+ – Wenn das Python 3-Kompatibilitätsflag
-3auf der Kommandozeile angegeben wird, gibt der Import von optparse eine DeprecationWarning aus. Andernfalls werden keine Warnungen ausgegeben. - Python 3.2+ – Der Import von optparse gibt eine PendingDeprecationWarning aus, die standardmäßig nicht angezeigt wird.
Es ist zu beachten, dass kein Entfernungsdatum für optparse vorgeschlagen wird.
Aktualisierungen der getopt-Dokumentation
Das getopt-Modul wird nicht veraltet sein. Seine Dokumentation wird jedoch an einigen Stellen aktualisiert, um auf argparse zu verweisen. Am Anfang des Moduls wird die folgende Notiz hinzugefügt.
Das getopt-Modul ist ein Parser für Kommandozeilenoptionen, dessen API so konzipiert ist, dass sie Benutzern der C getopt-Funktion vertraut ist. Benutzer, die mit der C getopt-Funktion nicht vertraut sind oder weniger Code schreiben und bessere Hilfe- und Fehlermeldungen erhalten möchten, sollten die Verwendung des argparse-Moduls in Erwägung ziehen.
Zusätzlich wird nach dem letzten getopt-Beispiel die folgende Notiz hinzugefügt.
Beachten Sie, dass eine äquivalente Kommandozeilenschnittstelle mit weniger Code durch die Verwendung des argparse-Moduls erstellt werden könnte.import argparse if __name__ == '__main__': parser = argparse.ArgumentParser() parser.add_argument('-o', '--output') parser.add_argument('-v', dest='verbose', action='store_true') args = parser.parse_args() # ... do something with args.output ... # ... do something with args.verbose ..
Zurückgestellt: String-Formatierung
Das argparse-Modul unterstützt Python von 2.3 bis 3.2 und stützt sich daher auf die traditionelle %(foo)s-String-Formatierung. Es wurde vorgeschlagen, dass es besser wäre, die neue {foo}-String-Formatierung zu verwenden [13]. Es gab einige Diskussionen darüber, wie dies am besten für Module in der Standardbibliothek geschehen könnte [14], und mehrere Personen entwickeln Funktionen zur automatischen Konvertierung von %-Formatierung in {}-Formatierung [15] [16]. Wenn eine dieser Funktionen in die Standardbibliothek aufgenommen wird, wird argparse sie zur Unterstützung beider Formatierungsstile verwenden.
Abgelehnt: getopt-Kompatibilitätsmethoden
Zuvor, als dieser PEP die Veraltung von getopt und optparse vorschlug, gab es einige Diskussionen über das Hinzufügen einer Methode wie:
ArgumentParser.add_getopt_arguments(options[, long_options])
Diese Methode wird jedoch aus mehreren Gründen nicht hinzugefügt.
- Das getopt-Modul wird nicht veraltet, daher besteht weniger Bedarf.
- Diese Methode würde die Umstellung für getopt-Benutzer, die bereits Nutzungsnachrichten pflegten, nicht wirklich erleichtern, da die obige API keine Möglichkeit bietet, Argumenten Hilfenachrichten hinzuzufügen.
- Einige Benutzer von getopt halten es für sehr wichtig, dass nur ein einziger Funktionsaufruf erforderlich ist. Die obige API erfüllt diese Anforderung nicht, da auch
ArgumentParser()undparse_args()aufgerufen werden müssen.
Außerhalb des Rahmens: Verschiedene Funktionsanfragen
Mehrere Funktionsanfragen für argparse wurden in der Diskussion dieses PEPs gestellt.
- Unterstützung von Argument-Standardwerten aus Umgebungsvariablen.
- Unterstützung von Argument-Standardwerten aus Konfigurationsdateien.
- Unterstützung von „foo –help subcommand“ zusätzlich zum derzeit unterstützten „foo subcommand –help“.
Dies sind alles vernünftige Funktionsanfragen für das argparse-Modul, aber sie liegen außerhalb des Rahmens dieses PEPs und wurden an den argparse-Issue-Tracker weitergeleitet.
Diskussion: sys.stderr und sys.exit
Es gab einige Bedenken, dass argparse standardmäßig immer nach sys.stderr schreibt und immer sys.exit aufruft, wenn ungültige Argumente bereitgestellt werden. Dies ist das gewünschte Verhalten für die überwiegende Mehrheit der argparse-Anwendungsfälle, die sich um einfache Kommandozeilenoberflächen drehen. In einigen Fällen kann es jedoch wünschenswert sein, zu verhindern, dass argparse beendet wird, oder es seine Nachrichten in etwas anderes als sys.stderr schreiben zu lassen. Diese Anwendungsfälle können unterstützt werden, indem ArgumentParser abgeleitet und die Methoden exit oder _print_message überschrieben werden. Letzteres ist ein undokumentiertes Implementierungsdetail, könnte aber offiziell freigegeben werden, wenn sich dies als häufiger Bedarf erweist.
Referenzen
Urheberrecht
Dieses Dokument wurde gemeinfrei erklärt.
Quelle: https://github.com/python/peps/blob/main/peps/pep-0389.rst
Zuletzt geändert: 2025-02-01 08:59:27 GMT