Seien Sie vorsichtig beim Umgang mit booleschen Werten in Pythons argparse

Geschäft

Um Befehlszeilenargumente in Python zu behandeln, verwenden Sie die argv- oder argparse-Module des sys-Moduls.

Das argparse-Modul ermöglicht eine flexible Handhabung von Kommandozeilenargumenten, wobei jedoch Vorsicht geboten ist, wenn es um boolesche Werte (true, false) geht.

Hier finden Sie die folgenden Informationen.

  • argparse zur einfachen Definition von Argumenten
  • Geben Sie den Typ des Arguments (type) mit argparse an
  • Nicht “bool” als Argumenttyp von add_argument() angeben
  • Beurteilung durch bool()
  • Verwenden Sie das Argument Aktion anstelle des Argumenttyps.
  • Verwendung der Funktion strtobool()

argparse zur einfachen Definition von Argumenten

Das argparse-Modul erleichtert die Definition von Kommandozeilenargumenten.

Das argparse-Modul macht es einfach, benutzerfreundliche Kommandozeilenschnittstellen zu erstellen. Sie definieren, welche Argumente Ihr Programm benötigt, und argparse findet heraus, wie diese Optionen aus sys.argv zu analysieren sind. Das argparse-Modul erzeugt automatisch Hilfe- und Verwendungsmeldungen und gibt einen Fehler aus, wenn der Benutzer ungültige Argumente für das Programm angibt.
argparse — Parser for command-line options, arguments and sub-commands — Python 3.10.0 Documentation

Geben Sie den Typ des Arguments (type) mit argparse an

Eine nützliche Funktion von argparse ist die Angabe des Typs (type).

Wenn Sie z. B. einen Integer-Typ (int) angeben, wird das Argument automatisch in int umgewandelt, und es wird ein Fehler für Argumente ausgegeben, die nicht int sind.

Der Typ wird durch den Argumenttyp von add_argument() angegeben.

import argparse

parser = argparse.ArgumentParser()
parser.add_argument('arg_int', type=int)

args = parser.parse_args()
print(args.arg_int)
print(type(args.arg_int))

Führen Sie diese Datei über die Befehlszeile aus.

$ python argparse_type_int.py 100
100
<type 'int'>

Das Argument 100 wird als int gelesen.

Wenn ein Nicht-Int-Wert als Argument verwendet wird, tritt ein Fehler auf.

$ python argparse_type_int.py foo
usage: argparse_type_int.py [-h] arg_int
argparse_type_int.py: error: argument arg_int: invalid int value: 'foo'

$ python argparse_type_int.py 1.23
usage: argparse_type_int.py [-h] arg_int
argparse_type_int.py: error: argument arg_int: invalid int value: '1.23'

Sehr nützlich, um unerwartete Argumente vorzutragen.

Nicht “bool” als Argumenttyp von add_argument() angeben

Es ist wichtig zu beachten, dass bool, wie int und float, nicht wie erwartet funktioniert, wenn Sie bool als Argumenttyp von add_argument() angeben.

import argparse

parser = argparse.ArgumentParser()
parser.add_argument('arg_bool', type=bool)

args = parser.parse_args()
print(args.arg_bool)
print(type(args.arg_bool))

Führen Sie diese Datei über die Befehlszeile aus.

$ python argparse_type_bool.py True
True
<type 'bool'>

Wenn true als Argument verwendet wird, wird es als bool vom Typ true gelesen. Dies ist das erwartete Verhalten, aber das Problem ist der folgende Fall.

$ python argparse_type_bool.py False
True
<type 'bool'>

$ python argparse_type_bool.py bar
True
<type 'bool'>

Wenn Sie false oder eine andere Zeichenkette als Argument verwenden, wird sie als true gelesen.

Der Grund dafür ist, dass bei der Angabe von type=xxx in add_argument() das Argument an xxx() übergeben wird.

Ist beispielsweise type=int, wird das Argument an int() übergeben; ist type=float, dann float().

Dasselbe gilt für type=bool, was bedeutet, dass das Argument an bool() übergeben wird.

Beurteilung durch bool()

Dieses bool() ist eine knifflige Angelegenheit.

Die folgenden Werte werden als falsch angesehen:

  • None
  • false
  • Null bei numerischen Typen. Zum Beispiel, die folgenden Werte
    • 0
    • 0.0
    • 0j
  • Eine leere Sequenz. Zum Beispiel
    • ''
    • ()
    • []
  • Leeres Mapping. Zum Beispiel
    • {}

Bei allen anderen Werten wird angenommen, dass sie wahr sind – daher sind Objekte vieler Typen immer wahr. Operationen und integrierte Funktionen, die boolesche Ergebnisse liefern, geben immer 0 oder False als falschen Wert und 1 oder True als wahren Wert zurück, sofern nicht anders angegeben.

Daher werden alle nicht leeren Zeichenketten, die an bool() übergeben werden, unabhängig davon, ob sie 'true' oder 'false' sind, true zurückgeben. Nur leere Zeichenketten sind falsch.

print(bool('True'))
print(bool('False'))
print(bool('abc'))
# True
# True
# True

print(bool(''))
# False

Wenn type=bool in add_argument() festgelegt ist, wird das Argument an bool() übergeben. Wenn also, wie im obigen Beispiel gezeigt, false als Argument verwendet wird, wird es von bool() in die Zeichenkette “False” umgewandelt und als true gelesen.

Verwenden Sie das Argument Aktion anstelle des Argumenttyps.

Wenn Sie boolesche Werte in argparse verwenden wollen, geben Sie 'store_true' oder 'store_false' für das Argument action an.

  • 'store_true'
  • 'store_false'

Dies sind spezielle Versionen von “store_const”, die True bzw. False speichern. Außerdem setzen sie die Standardwerte auf False bzw. True, und zwar in dieser Reihenfolge.
argparse — Parser for command-line options, arguments and sub-commands — Python 3.10.0 Documentation

import argparse

parser = argparse.ArgumentParser()
parser.add_argument('--en', action='store_true')

args = parser.parse_args()
print(args.en)
print(type(args.en))

In diesem Beispiel werden die folgenden Optionen angegeben.
--enWenn en also nicht als true gesetzt ist, wird es als false geladen, was der Standardwert von en ist.

$ python argparse_option_bool.py --en
True
<type 'bool'>

$ python argparse_option_bool.py
False
<type 'bool'>

Wenn Sie den Standardwert auf true und false setzen wollen, wenn die Option hinzugefügt wird, gehen Sie wie folgt vor.
action='store_false'

Verwendung der Funktion strtobool()

Wenn Sie anstelle von Optionen Positionsargumente verwenden möchten, können Sie auch die Funktion strtobool() verwenden.

strtobool() ist eine Funktion, die eine Zeichenkette in true (1) oder false (0) umwandelt.

Konvertiert eine boolesche Zeichenfolge in true (1) oder false (0).
Die wahren Werte lauten wie folgt

  • y
  • yes
  • true
  • on
  • 1

Falsche Werte sind wie folgt.

  • n
  • no
  • f
  • false
  • off
  • 0

Wenn val nicht einer der oben genannten Werte ist, wird ValueError ausgelöst.

9. API Reference – strtobool() — Python 3.10.0 Documentation

Es wird nicht zwischen Groß- und Kleinschreibung unterschieden, so dass Sie z. B. die folgende Zeichenkette verwenden können; jede andere Zeichenkette führt zu einem Fehler.

  • 'TRUE'
  • 'True'
  • 'YES'
from distutils.util import strtobool

print(strtobool('true'))
print(strtobool('True'))
print(strtobool('TRUE'))
# 1
# 1
# 1

print(strtobool('t'))
print(strtobool('yes'))
print(strtobool('y'))
print(strtobool('on'))
print(strtobool('1'))
# 1
# 1
# 1
# 1
# 1

print(strtobool('false'))
print(strtobool('False'))
print(strtobool('FALSE'))
# 0
# 0
# 0

print(strtobool('f'))
print(strtobool('no'))
print(strtobool('n'))
print(strtobool('off'))
print(strtobool('0'))
# 0
# 0
# 0
# 0
# 0

# print(strtobool('abc'))
# ValueError: invalid truth value 'abc'

Der Name ist strtobool(), aber der Rückgabewert ist nicht bool, sondern int (1 oder 0).

print(type(strtobool('true')))
# <class 'int'>

Wie bereits geschrieben, wird das Argument an xxx() übergeben, wenn type=xxx in add_argument() von argparse angegeben wird. Daher können wir das Folgende tun.
type=strtobool

import argparse
from distutils.util import strtobool

parser = argparse.ArgumentParser()
parser.add_argument('arg_bool', type=strtobool)

args = parser.parse_args()
print(args.arg_bool)
print(type(args.arg_bool))

Der Rückgabewert ist kein bool-Typ, sondern ein int-Typ 1 oder 0, aber er kann wahre oder falsche Werte mit true oder false als Argumente lesen.

$ python argparse_type_strtobool.py true
1
<type 'int'>

$ python argparse_type_strtobool.py false
0
<type 'int'>

Auch wenn das Argument nicht erwartet wird, wird eine Fehlermeldung erzeugt.

$ python argparse_type_strtobool.py bar
usage: argparse_type_strtobool.py [-h] arg_bool
argparse_type_strtobool.py: error: argument arg_bool: invalid strtobool value: 'bar'