Wees voorzichtig met Booleaanse waarden in Python’s argparse

Bedrijf

Om commandoregel argumenten in Python te behandelen, gebruik je de argv of argparse modules van de sys module.

De argparse module laat een flexibele behandeling van commandoregel argumenten toe, maar er moet voorzichtig omgesprongen worden met Booleaanse waarden (waar, vals).

De volgende informatie wordt hier verstrekt.

  • argparse voor eenvoudige definitie van argumenten
  • Specificeer het type van het argument (type) met argparse
  • Specificeer niet “bool” als argument type van add_argument()
  • Uitspraak door bool()
  • Gebruik het argument actie in plaats van het argument type.
  • De functie strtobool() gebruiken

argparse voor eenvoudige definitie van argumenten

De argparse module maakt het gemakkelijk om commandoregel argumenten te definiëren.

De argparse module maakt het gemakkelijk om gebruiksvriendelijke commando regel interfaces te maken. U definieert welke argumenten uw programma nodig heeft, en argparse zoekt uit hoe deze opties uit sys.argv gehaald moeten worden. argparse genereert automatisch help- en gebruiksberichten, en geeft een foutmelding als de gebruiker ongeldige argumenten opgeeft aan het programma. foutmelding als de gebruiker ongeldige argumenten opgeeft aan het programma.
argparse — Parser for command-line options, arguments and sub-commands — Python 3.10.0 Documentation

Specificeer het type van het argument (type) met argparse

Een handige functie van argparse is om het type (type) op te geven.

Indien u bijvoorbeeld een integer (int) type specificeert, zal het argument automatisch naar int worden geconverteerd en ook een foutmelding geven voor argumenten die geen int zijn.

Het type wordt gespecificeerd door het argumenttype van add_argument().

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))

Voer dit bestand uit vanaf de commandoregel.

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

Argument 100 wordt gelezen als int.

Als een niet-int waarde als argument wordt gebruikt, treedt een fout op.

$ 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'

Erg handig om onverwachte argumenten uit te spelen.

Specificeer niet “bool” als argument type van add_argument()

Het is belangrijk op te merken dat bool, net als int en float, niet zal werken zoals verwacht als je bool specificeert als argument type van add_argument().

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))

Voer dit bestand uit vanaf de commandoregel.

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

Als true als argument wordt gebruikt, zal het worden gelezen als een bool van het type true. Dit is het verwachte gedrag, maar het probleem is het volgende geval.

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

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

Als je false of een andere string als argument gebruikt, zal het als true gelezen worden.

De reden waarom dit gebeurt is dat wanneer type=xxx wordt opgegeven in add_argument(), het argument wordt doorgegeven aan xxx().

Bijvoorbeeld, indien type=int, zal het argument doorgegeven worden aan int(); indien type=float, dan float().

Hetzelfde geldt voor type=bool, wat betekent dat het argument zal worden doorgegeven aan bool().

Uitspraak door bool()

Deze bool() is een lastige.

De volgende waarden worden als onjuist beschouwd:

  • None
  • false
  • Nul in numerieke typen. Bijvoorbeeld, de volgende waarden
    • 0
    • 0.0
    • 0j
  • Een lege reeks. Bijvoorbeeld
    • ''
    • ()
    • []
  • Lege mapping. Bijvoorbeeld
    • {}

Alle andere waarden worden verondersteld waar te zijn – dus objecten van vele types zijn altijd waar. Operaties en ingebouwde functies die Booleaanse resultaten teruggeven, geven altijd 0 of False terug als de valse waarde en 1 of True als de ware waarde, tenzij anders vermeld.

Daarom zullen alle niet-lege strings die doorgegeven worden aan bool(), of ze nu 'true' of 'false' zijn, true teruggeven. Alleen lege strings zullen vals zijn.

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

print(bool(''))
# False

Wanneer type=bool is ingesteld in add_argument(), wordt het argument doorgegeven aan bool(). Daarom, zoals in het voorbeeld hierboven, als false wordt gebruikt als argument, zal het door bool() worden geconverteerd als de string 'False' en worden gelezen als true.

Gebruik het argument actie in plaats van het argument type.

Indien u Booleaanse waarden wilt gebruiken in argparse, specificeer dan 'store_true' of 'store_false' voor de argument actie.

  • 'store_true'
  • 'store_false'

Dit zullen speciale versies van 'store_const' zijn die respectievelijk True en False zullen opslaan. Bovendien zullen ze de standaardwaarden op respectievelijk False en True zetten, in die volgorde.
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 dit voorbeeld worden de volgende opties gegeven.
--enDaarom zal en, als het niet als waar is ingesteld, als onwaar worden geladen, wat de standaardwaarde van en is.

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

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

Als je de standaard op true wilt zetten, en false als de optie wordt toegevoegd, doe je gewoon het volgende.
action='store_false'

De functie strtobool() gebruiken

Als je positionele argumenten wilt gebruiken in plaats van opties, kun je ook de functie strtobool() gebruiken.

strtobool() is een functie die een string omzet in waar (1) of onwaar (0).

Converteert een booleaanse string naar waar (1) of onwaar (0).
De werkelijke waarden zijn als volgt

  • y
  • yes
  • true
  • on
  • 1

Valse waarden zijn als volgt.

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

Als val niet een van de bovenstaande is, roept het ValueError op.

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

Het is niet hoofdlettergevoelig, dus u kunt bijvoorbeeld het volgende gebruiken; elke andere string zal een foutmelding opleveren.

  • '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'

De naam is strtobool(), maar de return waarde is niet bool, maar int (1 of 0).

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

Zoals eerder geschreven, wanneer type=xxx wordt opgegeven in add_argument() van argparse, zal het argument worden doorgegeven aan xxx(). Daarom kunnen we het volgende doen.
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))

De terugkeerwaarde is geen bool type, maar een int type 1 of 0, maar het kan waar of onwaar waarden lezen met true of false als argumenten.

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

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

Ook als het argument niet wordt verwacht, zal een foutmelding worden gegenereerd.

$ 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'
Copied title and URL