1028 Stimmen

Boolean-Werte mit argparse analysieren

Ich möchte argparse verwenden, um boolean Befehlszeilenargumente zu parsen, die als "--foo True" oder "--foo False" geschrieben sind. Zum Beispiel:

my_program --my_boolean_flag False

Der folgende Testcode tut jedoch nicht, was ich möchte:

import argparse
parser = argparse.ArgumentParser(description="Mein Parser")
parser.add_argument("--my_bool", type=bool)
cmd_line = ["--my_bool", "False"]
parsed_args = parser.parse(cmd_line)

Leider ergibt parsed_args.my_bool True. Dies ist auch der Fall, wenn ich cmd_line zu ["--my_bool", ""] ändere, was überraschend ist, da bool("") zu False ausgewertet wird.

Wie kann ich argparse dazu bringen, "False", "F" und deren Kleinschreibungsvarianten als False zu parsen?

1393voto

mgilson Punkte 280928

Ich denke, eine kanonischere Möglichkeit, dies zu tun, ist über:

Befehl --Feature

und

Befehl --kein-Feature

argparse unterstützt diese Version gut:

Python 3.9+:

parser.add_argument('--feature', action=argparse.BooleanOptionalAction)

Python < 3.9:

parser.add_argument('--feature', action='store_true')
parser.add_argument('--no-feature', dest='feature', action='store_false')
parser.set_defaults(feature=True)

Natürlich, wenn du wirklich die --arg -Version möchtest, könntest du ast.literal_eval als "type" übergeben oder eine benutzerdefinierte Funktion ...

def t_or_f(arg):
    ua = str(arg).upper()
    if 'TRUE'.startswith(ua):
       return True
    elif 'FALSE'.startswith(ua):
       return False
    else:
       pass  #Fehlerbedingung vielleicht?

492voto

Maxim Punkte 6387

Noch eine Lösung, die die vorherigen Vorschläge verwendet, aber mit dem "korrekten" Syntaxfehler von argparse:

def str2bool(v):
    if isinstance(v, bool):
        return v
    if v.lower() in ('ja', 'wahr', 't', 'y', '1'):
        return True
    elif v.lower() in ('nein', 'falsch', 'f', 'n', '0'):
        return False
    else:
        raise argparse.ArgumentTypeError('Boolean-Wert erwartet.')

Dies ist sehr nützlich, um Schalter mit Standardwerten zu erstellen; zum Beispiel

parser.add_argument("--nice", type=str2bool, nargs='?',
                        const=True, default=False,
                        help="Aktiviere den Nicemodus.")

ermöglicht es mir, Folgendes zu verwenden:

script --nice
script --nice 

und trotzdem einen Standardwert zu verwenden (spezifisch für die Benutzereinstellungen). Ein (mittelbar verwandter) Nachteil bei diesem Ansatz ist, dass die 'nargs' ein positionales Argument erfassen könnte - siehe diese verwandte Frage und diese argparse-Fehlermeldung.

368voto

fnkr Punkte 8118

Wenn Sie --feature und --no-feature gleichzeitig zulassen möchten (der letzte gewinnt)

Dies ermöglicht es Benutzern, eine Shell-Alias mit --feature zu erstellen und sie mit --no-feature zu überschreiben.

Python 3.9 und höher

parser.add_argument('--feature', default=True, action=argparse.BooleanOptionalAction)

Python 3.8 und darunter

Ich empfehle die Antwort von mgilson:

parser.add_argument('--feature', dest='feature', action='store_true')
parser.add_argument('--no-feature', dest='feature', action='store_false')
parser.set_defaults(feature=True)

Wenn Sie --feature und --no-feature NICHT gleichzeitig zulassen möchten

Sie können eine gegenseitig ausschließende Gruppe verwenden:

feature_parser = parser.add_mutually_exclusive_group(required=False)
feature_parser.add_argument('--feature', dest='feature', action='store_true')
feature_parser.add_argument('--no-feature', dest='feature', action='store_false')
parser.set_defaults(feature=True)

Sie können diesen Helfer verwenden, wenn Sie viele davon einstellen werden:

def add_bool_arg(parser, name, default=False):
    group = parser.add_mutually_exclusive_group(required=False)
    group.add_argument('--' + name, dest=name, action='store_true')
    group.add_argument('--no-' + name, dest=name, action='store_false')
    parser.set_defaults(**{name:default})

add_bool_arg(parser, 'useful-feature')
add_bool_arg(parser, 'even-more-useful-feature')

124voto

Schaki Punkte 1485

Hier ist eine weitere Variante ohne zusätzliche Zeile(n) zum Festlegen von Standardwerten. Der boolesche Wert wird immer zugewiesen, so dass er in logischen Anweisungen verwendet werden kann, ohne vorher zu überprüfen:

import argparse
parser = argparse.ArgumentParser(description="Parse bool")
parser.add_argument("--do-something", default=False, action="store_true",
                    help="Flag, um etwas zu tun")
args = parser.parse_args()

if args.do_something:
     print("Mache etwas")
else:
     print("Mache nichts")

print(f"Überprüfen, dass args.do_something={args.do_something} immer ein Bool ist.")

87voto

Evalds Urtans Punkte 5836

Einzelliner:

parser.add_argument('--is_debug', default=False, type=lambda x: (str(x).lower() == 'true'))

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X