Argparse Tutorial

Autor:

Tshepang Mbambo

Dieses Tutorial soll eine sanfte Einführung in argparse, das empfohlene Modul zum Parsen von Kommandozeilen in der Python-Standardbibliothek, sein.

Hinweis

Die Standardbibliothek enthält zwei weitere Bibliotheken, die direkt mit der Verarbeitung von Kommandozeilenparametern zusammenhängen: das Low-Level-Modul optparse (das möglicherweise mehr Code zur Konfiguration für eine gegebene Anwendung erfordert, aber auch einer Anwendung erlaubt, Verhaltensweisen anzufordern, die argparse nicht unterstützt) und das sehr Low-Level-Modul getopt (das speziell als Äquivalent zu den getopt()-Funktionsfamilien dient, die für C-Programmierer verfügbar sind). Während keines dieser Module direkt in dieser Anleitung behandelt wird, stammen viele der Kernkonzepte in argparse ursprünglich aus optparse, daher werden einige Aspekte dieses Tutorials auch für optparse-Benutzer relevant sein.

Konzepte

Lassen Sie uns die Art von Funktionalität zeigen, die wir in diesem einführenden Tutorial untersuchen werden, indem wir den Befehl ls verwenden

$ ls
cpython  devguide  prog.py  pypy  rm-unused-function.patch
$ ls pypy
ctypes_configure  demo  dotviewer  include  lib_pypy  lib-python ...
$ ls -l
total 20
drwxr-xr-x 19 wena wena 4096 Feb 18 18:51 cpython
drwxr-xr-x  4 wena wena 4096 Feb  8 12:04 devguide
-rwxr-xr-x  1 wena wena  535 Feb 19 00:05 prog.py
drwxr-xr-x 14 wena wena 4096 Feb  7 00:59 pypy
-rw-r--r--  1 wena wena  741 Feb 18 01:01 rm-unused-function.patch
$ ls --help
Usage: ls [OPTION]... [FILE]...
List information about the FILEs (the current directory by default).
Sort entries alphabetically if none of -cftuvSUX nor --sort is specified.
...

Einige Konzepte, die wir aus den vier Befehlen lernen können

  • Der Befehl ls ist nützlich, wenn er ohne Optionen ausgeführt wird. Er zeigt standardmäßig den Inhalt des aktuellen Verzeichnisses an.

  • Wenn wir mehr als das wollen, was er standardmäßig bietet, teilen wir ihm ein wenig mehr mit. In diesem Fall möchten wir, dass er ein anderes Verzeichnis anzeigt, pypy. Was wir getan haben, ist die Angabe eines sogenannten Positionsarguments. Es wird so genannt, weil das Programm allein aufgrund seiner Position in der Kommandozeile weiß, was es mit dem Wert tun soll. Dieses Konzept ist relevanter für einen Befehl wie cp, dessen grundlegendste Verwendung cp QUELLE ZIEL ist. Die erste Position ist *was kopiert werden soll*, und die zweite Position ist *wohin es kopiert werden soll*.

  • Wenn wir nun das Verhalten des Programms ändern wollen. In unserem Beispiel zeigen wir mehr Informationen für jede Datei an, anstatt nur die Dateinamen anzuzeigen. Das -l ist in diesem Fall ein optionales Argument.

  • Das ist ein Ausschnitt aus dem Hilfetext. Er ist sehr nützlich, da man auf ein Programm stößt, das man noch nie zuvor benutzt hat, und einfach durch Lesen seines Hilfetextes herausfinden kann, wie es funktioniert.

Die Grundlagen

Beginnen wir mit einem sehr einfachen Beispiel, das (fast) nichts tut

import argparse
parser = argparse.ArgumentParser()
parser.parse_args()

Dies ist das Ergebnis der Ausführung des Codes

$ python prog.py
$ python prog.py --help
usage: prog.py [-h]

options:
  -h, --help  show this help message and exit
$ python prog.py --verbose
usage: prog.py [-h]
prog.py: error: unrecognized arguments: --verbose
$ python prog.py foo
usage: prog.py [-h]
prog.py: error: unrecognized arguments: foo

Hier passiert Folgendes

  • Das Ausführen des Skripts ohne Optionen führt dazu, dass nichts auf stdout ausgegeben wird. Nicht sehr nützlich.

  • Die zweite zeigt die Nützlichkeit des argparse-Moduls. Wir haben fast nichts getan, aber wir erhalten bereits eine nette Hilfemeldung.

  • Die Option --help, die auch zu -h abgekürzt werden kann, ist die einzige Option, die wir kostenlos erhalten (d. h. wir müssen sie nicht angeben). Die Angabe von etwas anderem führt zu einem Fehler. Aber selbst dann erhalten wir eine nützliche Nutzungsmeldung, ebenfalls kostenlos.

Einführung von Positionsargumenten

Ein Beispiel

import argparse
parser = argparse.ArgumentParser()
parser.add_argument("echo")
args = parser.parse_args()
print(args.echo)

Und Ausführung des Codes

$ python prog.py
usage: prog.py [-h] echo
prog.py: error: the following arguments are required: echo
$ python prog.py --help
usage: prog.py [-h] echo

positional arguments:
  echo

options:
  -h, --help  show this help message and exit
$ python prog.py foo
foo

Das passiert hier

  • Wir haben die Methode add_argument() hinzugefügt, mit der wir angeben, welche Kommandozeilenoptionen das Programm akzeptiert. In diesem Fall habe ich sie echo genannt, damit sie ihrer Funktion entspricht.

  • Das Aufrufen unseres Programms erfordert nun, dass wir eine Option angeben.

  • Die Methode parse_args() gibt tatsächlich einige Daten von den angegebenen Optionen zurück, in diesem Fall echo.

  • Die Variable ist eine Art „Magie“, die argparse kostenlos durchführt (d. h. es muss nicht angegeben werden, in welcher Variable dieser Wert gespeichert wird). Sie werden auch feststellen, dass sein Name mit dem Zeichenkettenargument übereinstimmt, das der Methode übergeben wurde, echo.

Beachten Sie jedoch, dass die Hilfemeldung zwar nett aussieht, aber derzeit nicht so hilfreich ist, wie sie sein könnte. Zum Beispiel sehen wir, dass wir echo als Positionsargument erhalten haben, aber wir wissen nicht, was es tut, außer durch Raten oder Lesen des Quellcodes. Machen wir es also ein wenig nützlicher

import argparse
parser = argparse.ArgumentParser()
parser.add_argument("echo", help="echo the string you use here")
args = parser.parse_args()
print(args.echo)

Und wir erhalten

$ python prog.py -h
usage: prog.py [-h] echo

positional arguments:
  echo        echo the string you use here

options:
  -h, --help  show this help message and exit

Nun, wie wäre es, etwas noch Nützlicheres zu tun

import argparse
parser = argparse.ArgumentParser()
parser.add_argument("square", help="display a square of a given number")
args = parser.parse_args()
print(args.square**2)

Dies ist das Ergebnis der Ausführung des Codes

$ python prog.py 4
Traceback (most recent call last):
  File "prog.py", line 5, in <module>
    print(args.square**2)
TypeError: unsupported operand type(s) for ** or pow(): 'str' and 'int'

Das ging nicht so gut. Das liegt daran, dass argparse die ihm übergebenen Optionen als Zeichenketten behandelt, es sei denn, wir sagen ihm etwas anderes. Sagen wir also argparse, dass diese Eingabe als Ganzzahl behandelt werden soll

import argparse
parser = argparse.ArgumentParser()
parser.add_argument("square", help="display a square of a given number",
                    type=int)
args = parser.parse_args()
print(args.square**2)

Dies ist das Ergebnis der Ausführung des Codes

$ python prog.py 4
16
$ python prog.py four
usage: prog.py [-h] square
prog.py: error: argument square: invalid int value: 'four'

Das hat gut geklappt. Das Programm bricht nun sogar hilfreich bei ungültigen Eingaben ab, bevor es fortfährt.

Einführung von optionalen Argumenten

Bisher haben wir mit Positionsargumenten gearbeitet. Sehen wir uns an, wie optionale hinzugefügt werden

import argparse
parser = argparse.ArgumentParser()
parser.add_argument("--verbosity", help="increase output verbosity")
args = parser.parse_args()
if args.verbosity:
    print("verbosity turned on")

Und die Ausgabe

$ python prog.py --verbosity 1
verbosity turned on
$ python prog.py
$ python prog.py --help
usage: prog.py [-h] [--verbosity VERBOSITY]

options:
  -h, --help            show this help message and exit
  --verbosity VERBOSITY
                        increase output verbosity
$ python prog.py --verbosity
usage: prog.py [-h] [--verbosity VERBOSITY]
prog.py: error: argument --verbosity: expected one argument

Hier passiert Folgendes

  • Das Programm ist so geschrieben, dass es etwas anzeigt, wenn --verbosity angegeben wird, und nichts anzeigt, wenn nicht.

  • Um zu zeigen, dass die Option tatsächlich optional ist, gibt es keinen Fehler, wenn das Programm ohne sie ausgeführt wird. Beachten Sie, dass standardmäßig, wenn ein optionales Argument nicht verwendet wird, der relevante Variablenwert, in diesem Fall args.verbosity, None als Wert erhält, weshalb er den Wahrheitswert des if-Statements nicht besteht.

  • Die Hilfemeldung ist etwas anders.

  • Bei Verwendung der Option --verbosity muss auch ein Wert angegeben werden, irgendein Wert.

Das obige Beispiel akzeptiert beliebige Ganzzahlwerte für --verbosity, aber für unser einfaches Programm sind nur zwei Werte tatsächlich nützlich, True oder False. Lassen Sie uns den Code entsprechend ändern

import argparse
parser = argparse.ArgumentParser()
parser.add_argument("--verbose", help="increase output verbosity",
                    action="store_true")
args = parser.parse_args()
if args.verbose:
    print("verbosity turned on")

Und die Ausgabe

$ python prog.py --verbose
verbosity turned on
$ python prog.py --verbose 1
usage: prog.py [-h] [--verbose]
prog.py: error: unrecognized arguments: 1
$ python prog.py --help
usage: prog.py [-h] [--verbose]

options:
  -h, --help  show this help message and exit
  --verbose   increase output verbosity

Hier passiert Folgendes

  • Die Option ist nun eher ein Flag als etwas, das einen Wert erfordert. Wir haben sogar den Namen der Option geändert, um dieser Idee zu entsprechen. Beachten Sie, dass wir nun ein neues Schlüsselwort angeben, action, und ihm den Wert "store_true" geben. Das bedeutet, dass, wenn die Option angegeben wird, der Wert True an args.verbose zugewiesen wird. Die Nicht-Angabe impliziert False.

  • Es beschwert sich, wenn ein Wert angegeben wird, im wahren Geiste dessen, was Flags tatsächlich sind.

  • Beachten Sie die geänderte Hilfemeldung.

Kurze Optionen

Wenn Sie mit der Nutzung der Kommandozeile vertraut sind, werden Sie bemerken, dass ich das Thema kurzer Versionen der Optionen noch nicht behandelt habe. Das ist ganz einfach

import argparse
parser = argparse.ArgumentParser()
parser.add_argument("-v", "--verbose", help="increase output verbosity",
                    action="store_true")
args = parser.parse_args()
if args.verbose:
    print("verbosity turned on")

Und hier geht's los

$ python prog.py -v
verbosity turned on
$ python prog.py --help
usage: prog.py [-h] [-v]

options:
  -h, --help     show this help message and exit
  -v, --verbose  increase output verbosity

Beachten Sie, dass die neue Fähigkeit auch im Hilfetext reflektiert wird.

Kombination von Positions- und optionalen Argumenten

Unser Programm wächst weiter in Komplexität

import argparse
parser = argparse.ArgumentParser()
parser.add_argument("square", type=int,
                    help="display a square of a given number")
parser.add_argument("-v", "--verbose", action="store_true",
                    help="increase output verbosity")
args = parser.parse_args()
answer = args.square**2
if args.verbose:
    print(f"the square of {args.square} equals {answer}")
else:
    print(answer)

Und jetzt die Ausgabe

$ python prog.py
usage: prog.py [-h] [-v] square
prog.py: error: the following arguments are required: square
$ python prog.py 4
16
$ python prog.py 4 --verbose
the square of 4 equals 16
$ python prog.py --verbose 4
the square of 4 equals 16
  • Wir haben ein Positionsargument zurückgebracht, daher die Beschwerde.

  • Beachten Sie, dass die Reihenfolge keine Rolle spielt.

Wie wäre es, wenn wir unserem Programm die Fähigkeit zurückgeben, mehrere Verbosity-Werte zu haben und sie tatsächlich zu nutzen

import argparse
parser = argparse.ArgumentParser()
parser.add_argument("square", type=int,
                    help="display a square of a given number")
parser.add_argument("-v", "--verbosity", type=int,
                    help="increase output verbosity")
args = parser.parse_args()
answer = args.square**2
if args.verbosity == 2:
    print(f"the square of {args.square} equals {answer}")
elif args.verbosity == 1:
    print(f"{args.square}^2 == {answer}")
else:
    print(answer)

Und die Ausgabe

$ python prog.py 4
16
$ python prog.py 4 -v
usage: prog.py [-h] [-v VERBOSITY] square
prog.py: error: argument -v/--verbosity: expected one argument
$ python prog.py 4 -v 1
4^2 == 16
$ python prog.py 4 -v 2
the square of 4 equals 16
$ python prog.py 4 -v 3
16

Diese sehen alle gut aus, bis auf die letzte, die einen Fehler in unserem Programm aufdeckt. Lassen Sie uns das beheben, indem wir die Werte einschränken, die die Option --verbosity akzeptieren kann

import argparse
parser = argparse.ArgumentParser()
parser.add_argument("square", type=int,
                    help="display a square of a given number")
parser.add_argument("-v", "--verbosity", type=int, choices=[0, 1, 2],
                    help="increase output verbosity")
args = parser.parse_args()
answer = args.square**2
if args.verbosity == 2:
    print(f"the square of {args.square} equals {answer}")
elif args.verbosity == 1:
    print(f"{args.square}^2 == {answer}")
else:
    print(answer)

Und die Ausgabe

$ python prog.py 4 -v 3
usage: prog.py [-h] [-v {0,1,2}] square
prog.py: error: argument -v/--verbosity: invalid choice: 3 (choose from 0, 1, 2)
$ python prog.py 4 -h
usage: prog.py [-h] [-v {0,1,2}] square

positional arguments:
  square                display a square of a given number

options:
  -h, --help            show this help message and exit
  -v, --verbosity {0,1,2}
                        increase output verbosity

Beachten Sie, dass die Änderung sich sowohl in der Fehlermeldung als auch im Hilfetext widerspiegelt.

Nun, lassen Sie uns einen anderen Ansatz zur Handhabung der Verbosity ausprobieren, der ziemlich üblich ist. Er entspricht auch der Art und Weise, wie die CPython-Ausführungsdatei ihr eigenes Verbosity-Argument behandelt (überprüfen Sie die Ausgabe von python --help)

import argparse
parser = argparse.ArgumentParser()
parser.add_argument("square", type=int,
                    help="display the square of a given number")
parser.add_argument("-v", "--verbosity", action="count",
                    help="increase output verbosity")
args = parser.parse_args()
answer = args.square**2
if args.verbosity == 2:
    print(f"the square of {args.square} equals {answer}")
elif args.verbosity == 1:
    print(f"{args.square}^2 == {answer}")
else:
    print(answer)

Wir haben eine weitere Aktion, „count“, eingeführt, um die Anzahl der Vorkommen bestimmter Optionen zu zählen.

$ python prog.py 4
16
$ python prog.py 4 -v
4^2 == 16
$ python prog.py 4 -vv
the square of 4 equals 16
$ python prog.py 4 --verbosity --verbosity
the square of 4 equals 16
$ python prog.py 4 -v 1
usage: prog.py [-h] [-v] square
prog.py: error: unrecognized arguments: 1
$ python prog.py 4 -h
usage: prog.py [-h] [-v] square

positional arguments:
  square           display a square of a given number

options:
  -h, --help       show this help message and exit
  -v, --verbosity  increase output verbosity
$ python prog.py 4 -vvv
16
  • Ja, es ist nun mehr ein Flag (ähnlich wie action="store_true") in der vorherigen Version unseres Skripts. Das sollte die Beschwerde erklären.

  • Es verhält sich auch ähnlich wie die Aktion „store_true“.

  • Hier ist eine Demonstration dessen, was die Aktion „count“ liefert. Sie haben wahrscheinlich schon eine solche Verwendung gesehen.

  • Und wenn Sie das Flag -v nicht angeben, gilt dieses Flag als None-Wert.

  • Wie erwartet, sollten wir bei Angabe der langen Form des Flags die gleiche Ausgabe erhalten.

  • Leider ist unsere Hilfsausgabe nicht sehr informativ über die neue Fähigkeit, die unser Skript erworben hat, aber das kann immer behoben werden, indem die Dokumentation für unser Skript verbessert wird (z. B. über das Schlüsselwortargument help).

  • Die letzte Ausgabe deckt einen Fehler in unserem Programm auf.

Lassen Sie uns beheben

import argparse
parser = argparse.ArgumentParser()
parser.add_argument("square", type=int,
                    help="display a square of a given number")
parser.add_argument("-v", "--verbosity", action="count",
                    help="increase output verbosity")
args = parser.parse_args()
answer = args.square**2

# bugfix: replace == with >=
if args.verbosity >= 2:
    print(f"the square of {args.square} equals {answer}")
elif args.verbosity >= 1:
    print(f"{args.square}^2 == {answer}")
else:
    print(answer)

Und das ist, was es liefert

$ python prog.py 4 -vvv
the square of 4 equals 16
$ python prog.py 4 -vvvv
the square of 4 equals 16
$ python prog.py 4
Traceback (most recent call last):
  File "prog.py", line 11, in <module>
    if args.verbosity >= 2:
TypeError: '>=' not supported between instances of 'NoneType' and 'int'
  • Die erste Ausgabe verlief gut und behebt den vorherigen Fehler. Das heißt, wir möchten, dass jeder Wert >= 2 so ausführlich wie möglich ist.

  • Dritte Ausgabe nicht so gut.

Lassen Sie uns diesen Fehler beheben

import argparse
parser = argparse.ArgumentParser()
parser.add_argument("square", type=int,
                    help="display a square of a given number")
parser.add_argument("-v", "--verbosity", action="count", default=0,
                    help="increase output verbosity")
args = parser.parse_args()
answer = args.square**2
if args.verbosity >= 2:
    print(f"the square of {args.square} equals {answer}")
elif args.verbosity >= 1:
    print(f"{args.square}^2 == {answer}")
else:
    print(answer)

Wir haben gerade ein weiteres Schlüsselwort eingeführt, default. Wir haben es auf 0 gesetzt, um es mit anderen Ganzzahlwerten vergleichen zu können. Denken Sie daran, dass, wenn ein optionales Argument nicht angegeben wird, es standardmäßig den Wert None erhält, und dieser nicht mit einem Ganzzahlwert verglichen werden kann (daher die TypeError-Ausnahme).

Und

$ python prog.py 4
16

Sie können mit dem, was wir bisher gelernt haben, ziemlich weit kommen, und wir haben nur an der Oberfläche gekratzt. Das argparse-Modul ist sehr mächtig, und wir werden uns noch ein wenig damit beschäftigen, bevor wir dieses Tutorial beenden.

Etwas fortgeschrittener

Was, wenn wir unser kleines Programm erweitern wollten, um andere Potenzen zu berechnen, nicht nur Quadrate

import argparse
parser = argparse.ArgumentParser()
parser.add_argument("x", type=int, help="the base")
parser.add_argument("y", type=int, help="the exponent")
parser.add_argument("-v", "--verbosity", action="count", default=0)
args = parser.parse_args()
answer = args.x**args.y
if args.verbosity >= 2:
    print(f"{args.x} to the power {args.y} equals {answer}")
elif args.verbosity >= 1:
    print(f"{args.x}^{args.y} == {answer}")
else:
    print(answer)

Ausgabe

$ python prog.py
usage: prog.py [-h] [-v] x y
prog.py: error: the following arguments are required: x, y
$ python prog.py -h
usage: prog.py [-h] [-v] x y

positional arguments:
  x                the base
  y                the exponent

options:
  -h, --help       show this help message and exit
  -v, --verbosity
$ python prog.py 4 2 -v
4^2 == 16

Beachten Sie, dass wir bisher die Verbosity-Stufe verwendet haben, um den angezeigten Text zu *ändern*. Das folgende Beispiel verwendet stattdessen die Verbosity-Stufe, um *mehr* Text anzuzeigen

import argparse
parser = argparse.ArgumentParser()
parser.add_argument("x", type=int, help="the base")
parser.add_argument("y", type=int, help="the exponent")
parser.add_argument("-v", "--verbosity", action="count", default=0)
args = parser.parse_args()
answer = args.x**args.y
if args.verbosity >= 2:
    print(f"Running '{__file__}'")
if args.verbosity >= 1:
    print(f"{args.x}^{args.y} == ", end="")
print(answer)

Ausgabe

$ python prog.py 4 2
16
$ python prog.py 4 2 -v
4^2 == 16
$ python prog.py 4 2 -vv
Running 'prog.py'
4^2 == 16

Spezifizierung mehrdeutiger Argumente

Wenn Unklarheit darüber besteht, ob ein Argument positionsbezogen oder für ein Argument bestimmt ist, kann -- verwendet werden, um parse_args() mitzuteilen, dass alles danach ein Positionsargument ist

>>> parser = argparse.ArgumentParser(prog='PROG')
>>> parser.add_argument('-n', nargs='+')
>>> parser.add_argument('args', nargs='*')

>>> # ambiguous, so parse_args assumes it's an option
>>> parser.parse_args(['-f'])
usage: PROG [-h] [-n N [N ...]] [args ...]
PROG: error: unrecognized arguments: -f

>>> parser.parse_args(['--', '-f'])
Namespace(args=['-f'], n=None)

>>> # ambiguous, so the -n option greedily accepts arguments
>>> parser.parse_args(['-n', '1', '2', '3'])
Namespace(args=[], n=['1', '2', '3'])

>>> parser.parse_args(['-n', '1', '--', '2', '3'])
Namespace(args=['2', '3'], n=['1'])

Konfliktierende Optionen

Bisher haben wir mit zwei Methoden einer argparse.ArgumentParser-Instanz gearbeitet. Führen wir eine dritte ein, add_mutually_exclusive_group(). Sie ermöglicht es uns, Optionen anzugeben, die miteinander in Konflikt stehen. Ändern wir auch den Rest des Programms, damit die neue Funktionalität sinnvoller ist: Wir führen die Option --quiet ein, die das Gegenteil der Option --verbose sein wird

import argparse

parser = argparse.ArgumentParser()
group = parser.add_mutually_exclusive_group()
group.add_argument("-v", "--verbose", action="store_true")
group.add_argument("-q", "--quiet", action="store_true")
parser.add_argument("x", type=int, help="the base")
parser.add_argument("y", type=int, help="the exponent")
args = parser.parse_args()
answer = args.x**args.y

if args.quiet:
    print(answer)
elif args.verbose:
    print(f"{args.x} to the power {args.y} equals {answer}")
else:
    print(f"{args.x}^{args.y} == {answer}")

Unser Programm ist nun einfacher, und wir haben aus Demonstrationsgründen einige Funktionalitäten verloren. Hier ist jedenfalls die Ausgabe

$ python prog.py 4 2
4^2 == 16
$ python prog.py 4 2 -q
16
$ python prog.py 4 2 -v
4 to the power 2 equals 16
$ python prog.py 4 2 -vq
usage: prog.py [-h] [-v | -q] x y
prog.py: error: argument -q/--quiet: not allowed with argument -v/--verbose
$ python prog.py 4 2 -v --quiet
usage: prog.py [-h] [-v | -q] x y
prog.py: error: argument -q/--quiet: not allowed with argument -v/--verbose

Das sollte leicht verständlich sein. Ich habe diese letzte Ausgabe hinzugefügt, damit Sie die Flexibilität sehen können, die Sie erhalten, d. h. die Mischung von Langform-Optionen mit Kurzform-Optionen.

Bevor wir schließen, möchten Sie Ihren Benutzern vielleicht den Hauptzweck Ihres Programms mitteilen, falls sie ihn nicht kennen

import argparse

parser = argparse.ArgumentParser(description="calculate X to the power of Y")
group = parser.add_mutually_exclusive_group()
group.add_argument("-v", "--verbose", action="store_true")
group.add_argument("-q", "--quiet", action="store_true")
parser.add_argument("x", type=int, help="the base")
parser.add_argument("y", type=int, help="the exponent")
args = parser.parse_args()
answer = args.x**args.y

if args.quiet:
    print(answer)
elif args.verbose:
    print(f"{args.x} to the power {args.y} equals {answer}")
else:
    print(f"{args.x}^{args.y} == {answer}")

Beachten Sie den leichten Unterschied im Nutzungstext. Beachten Sie die [-v | -q], die uns sagt, dass wir entweder -v oder -q verwenden können, aber nicht beides gleichzeitig

$ python prog.py --help
usage: prog.py [-h] [-v | -q] x y

calculate X to the power of Y

positional arguments:
  x              the base
  y              the exponent

options:
  -h, --help     show this help message and exit
  -v, --verbose
  -q, --quiet

Wie man die Ausgabe von argparse übersetzt

Die Ausgabe des argparse-Moduls, wie z. B. der Hilfetext und Fehlermeldungen, ist alle über das gettext-Modul übersetzbar. Dies ermöglicht Anwendungen, von argparse erzeugte Nachrichten einfach zu lokalisieren. Siehe auch Ihre Programme und Module internationalisieren.

Zum Beispiel in dieser argparse-Ausgabe

$ python prog.py --help
usage: prog.py [-h] [-v | -q] x y

calculate X to the power of Y

positional arguments:
  x              the base
  y              the exponent

options:
  -h, --help     show this help message and exit
  -v, --verbose
  -q, --quiet

Die Zeichenketten usage:, positional arguments:, options: und show this help message and exit sind alle übersetzbar.

Um diese Zeichenketten zu übersetzen, müssen sie zuerst in eine .po-Datei extrahiert werden. Zum Beispiel mit Babel, führen Sie diesen Befehl aus

$ pybabel extract -o messages.po /usr/lib/python3.12/argparse.py

Dieser Befehl extrahiert alle übersetzbaren Zeichenketten aus dem argparse-Modul und gibt sie in einer Datei namens messages.po aus. Dieser Befehl geht davon aus, dass Ihre Python-Installation sich in /usr/lib befindet.

Sie können den Speicherort des argparse-Moduls auf Ihrem System mit diesem Skript herausfinden

import argparse
print(argparse.__file__)

Sobald die Nachrichten in der .po-Datei übersetzt und die Übersetzungen mit gettext installiert sind, kann argparse die übersetzten Nachrichten anzeigen.

Um Ihre eigenen Zeichenketten in der argparse-Ausgabe zu übersetzen, verwenden Sie gettext.

Benutzerdefinierte Typkonverter

Das argparse-Modul ermöglicht es Ihnen, benutzerdefinierte Typkonverter für Ihre Kommandozeilenargumente anzugeben. Dies ermöglicht es Ihnen, Benutzereingaben zu ändern, bevor sie im argparse.Namespace gespeichert werden. Dies kann nützlich sein, wenn Sie die Eingabe vorverarbeiten müssen, bevor sie in Ihrem Programm verwendet wird.

Bei der Verwendung eines benutzerdefinierten Typkonverters können Sie jede aufrufbare Funktion verwenden, die ein einzelnes Zeichenkettenargument (den Argumentwert) entgegennimmt und den konvertierten Wert zurückgibt. Wenn Sie jedoch komplexere Szenarien behandeln müssen, können Sie stattdessen eine benutzerdefinierte Aktionsklasse mit dem Parameter action verwenden.

Nehmen wir zum Beispiel an, Sie möchten Argumente mit verschiedenen Präfixen behandeln und sie entsprechend verarbeiten

import argparse

parser = argparse.ArgumentParser(prefix_chars='-+')

parser.add_argument('-a', metavar='<value>', action='append',
                    type=lambda x: ('-', x))
parser.add_argument('+a', metavar='<value>', action='append',
                    type=lambda x: ('+', x))

args = parser.parse_args()
print(args)

Ausgabe

$ python prog.py -a value1 +a value2
Namespace(a=[('-', 'value1'), ('+', 'value2')])

In diesem Beispiel haben wir

  • Einen Parser mit benutzerdefinierten Präfixzeichen mit dem Parameter prefix_chars erstellt.

  • Zwei Argumente definiert, -a und +a, die den Parameter type verwendet haben, um benutzerdefinierte Typkonverter zu erstellen und den Wert in einem Tupel mit dem Präfix zu speichern.

Ohne die benutzerdefinierten Typkonverter wären die Argumente -a und +a als dasselbe Argument behandelt worden, was unerwünscht gewesen wäre. Durch die Verwendung benutzerdefinierter Typkonverter konnten wir die beiden Argumente unterscheiden.

Schlussfolgerung

Das argparse-Modul bietet weit mehr als hier gezeigt wird. Seine Dokumentation ist sehr detailliert und gründlich und voller Beispiele. Nachdem Sie dieses Tutorial durchgearbeitet haben, sollten Sie sie problemlos verdauen können, ohne sich überfordert zu fühlen.