Vær forsigtig, når du håndterer boolske værdier i Pythons argparse

Forretning

Hvis du vil håndtere kommandolinjeargumenter i Python, skal du bruge modulerne argv eller argparse i sys-modulet.

Argparse-modulet giver mulighed for fleksibel håndtering af kommandolinjeargumenter, men man skal være forsigtig ved håndtering af boolske værdier (true, false).

Her findes følgende oplysninger.

  • argparse til nem definition af argumenter
  • Angiv argumentets type (type) med argparse
  • Du må ikke angive “bool” som argumenttype i add_argument()
  • Dom af bool()
  • Brug argumenthandlingen i stedet for argumenttypen.
  • Brug af funktionen strtobool()

argparse til nem definition af argumenter

Modulet argparse gør det nemt at definere kommandolinjeargumenter.

Argparse-modulet gør det nemt at skabe brugervenlige kommandolinjeinterfaces. Du definerer, hvilke argumenter dit program har brug for, og argparse finder ud af, hvordan disse muligheder skal analyseres fra sys.argv. argparse-modulet genererer automatisk hjælp og brugsbeskeder og giver en fejl, hvis brugeren angiver ugyldige argumenter til programmet. fejl, hvis brugeren angiver ugyldige argumenter til programmet.
argparse — Parser for command-line options, arguments and sub-commands — Python 3.10.0 Documentation

Angiv argumentets type (type) med argparse

En nyttig funktion i argparse er at angive typen (type).

Hvis du f.eks. angiver en heltalstype (int), konverteres argumentet automatisk til int, og der opstår også en fejl for argumenter, der ikke er int.

Typen er angivet ved argumenttypen i 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))

Kør denne fil fra kommandolinjen.

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

Argument 100 læses som int.

Hvis en ikke-int-værdi anvendes som argument, opstår der en fejl.

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

Meget nyttig til at spille uventede argumenter.

Du må ikke angive “bool” som argumenttype i add_argument()

Det er vigtigt at bemærke, at bool, ligesom int og float, ikke vil fungere som forventet, hvis du angiver bool som argumenttype for 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))

Kør denne fil fra kommandolinjen.

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

Hvis true bruges som argument, vil det blive læst som en bool af typen true. Dette er den forventede adfærd, men problemet er følgende tilfælde.

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

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

Hvis du bruger false eller en anden streng som argument, vil det blive læst som true.

Grunden til, at dette sker, er, at når type=xxx er angivet i add_argument(), overføres argumentet til xxx().

Hvis type=int, vil argumentet f.eks. blive sendt til int(); hvis type=float, vil det blive sendt til float().

Det samme gælder for type=bool, hvilket betyder, at argumentet vil blive overført til bool().

Dom af bool()

Denne bool() er en vanskelig sag.

Følgende værdier anses for at være falske:

  • None
  • false
  • Nul i numeriske typer. For eksempel følgende værdier
    • 0
    • 0.0
    • 0j
  • En tom sekvens. For eksempel
    • ''
    • ()
    • []
  • Tomme kortlægninger. For eksempel
    • {}

Alle andre værdier antages at være sande – således er objekter af mange typer altid sande. Operationer og indbyggede funktioner, der returnerer boolske resultater, returnerer altid 0 eller False som den falske værdi og 1 eller True som den sande værdi, medmindre andet er angivet.

Derfor vil alle ikke-tomme strenge, der er overgivet til bool(), uanset om de er “sande” eller “falske”, returnere sandt. Kun tomme strenge vil være falske.

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

print(bool(''))
# False

Når type=bool er angivet i add_argument(), overføres argumentet til bool(). Derfor, som vist i eksemplet ovenfor, hvis false bruges som argument, vil det blive konverteret af bool() som strengen “False” og læst som true.

Brug argumenthandlingen i stedet for argumenttypen.

Hvis du ønsker at bruge boolske værdier i argparse, skal du angive “store_true” eller “store_false” for argumenthandlingen.

  • 'store_true'
  • 'store_false'

Disse vil være særlige versioner af “store_const”, som gemmer henholdsvis True og False. Desuden vil de sætte standardværdierne til henholdsvis False og True i denne rækkefølge.
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))

I dette eksempel er følgende indstillinger angivet.
--enHvis en ikke er angivet som sand, vil den derfor blive indlæst som falsk, hvilket er standardværdien for en.

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

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

Hvis du vil indstille standardindstillingen til sand og falsk, når indstillingen tilføjes, skal du blot gøre følgende.
action='store_false'

Brug af funktionen strtobool()

Hvis du ønsker at bruge positionelle argumenter i stedet for indstillinger, kan du også bruge funktionen strtobool().

strtobool() er en funktion, der konverterer en streng til sand (1) eller falsk (0).

Konverterer en boolsk streng til sand (1) eller falsk (0).
De sande værdier er som følger

  • y
  • yes
  • true
  • on
  • 1

De falske værdier er som følger.

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

Hvis val ikke er en af de ovennævnte værdier, udløses ValueError.

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

Der er ikke forskel på store og små bogstaver, så du kan f.eks. bruge følgende; enhver anden streng vil resultere i en fejl.

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

Navnet er strtobool(), men den returnerede værdi er ikke bool, men int (1 eller 0).

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

Som tidligere skrevet, når type=xxx er angivet i add_argument() i argparse, vil argumentet blive overført til xxx(). Derfor kan vi gøre følgende.
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))

Returværdien er ikke en bool-type, men en int-type 1 eller 0, men den kan læse sande eller falske værdier med true eller false som argumenter.

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

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

Hvis argumentet ikke er forventet, vil der også blive genereret en fejl korrekt.

$ 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