Var försiktig när du hanterar boolska värden i Pythons argparse

Företag

För att hantera kommandoradsargument i Python använder du modulerna argv eller argparse i sys-modulen.

Modulen argparse gör det möjligt att hantera kommandoradsargument på ett flexibelt sätt, men man måste vara försiktig när man hanterar boolska värden (sant, falskt).

Här finns följande information.

  • argparse för enkel definition av argument
  • Ange argumentets typ (typ) med argparse.
  • Ange inte ”bool” som argumenttyp för add_argument()
  • Dom genom bool()
  • Använd argumentåtgärden i stället för argumenttypen.
  • Använda funktionen strtobool()

argparse för enkel definition av argument

Modulen argparse gör det enkelt att definiera kommandoradsargument.

Modulen argparse gör det enkelt att skapa användarvänliga kommandoradsgränssnitt. Du definierar vilka argument som ditt program behöver och argparse kommer att lista ut hur dessa alternativ ska analyseras från sys.argv. argparse-modulen genererar automatiskt hjälp- och användningsmeddelanden och ger upphov till ett fel om användaren anger ogiltiga argument till programmet. fel när användaren anger ogiltiga argument till programmet.
argparse — Parser for command-line options, arguments and sub-commands — Python 3.10.0 Documentation

Ange argumentets typ (typ) med argparse.

En användbar funktion i argparse är att ange typen (type).

Om du t.ex. anger en heltalstyp (int) konverteras argumentet automatiskt till int och det uppstår ett fel för argument som inte är int.

Typen anges av 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 den här filen från kommandoraden.

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

Argument 100 läses som int.

Om ett icke-int-värde används som argument uppstår ett fel.

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

Mycket användbar för att spela oväntade argument.

Ange inte ”bool” som argumenttyp för add_argument()

Det är viktigt att notera att bool, liksom int och float, inte fungerar som förväntat om du anger bool som argumenttyp för 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 den här filen från kommandoraden.

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

Om true används som argument kommer det att läsas som en bool av typen true. Detta är det förväntade beteendet, men problemet är följande fall.

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

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

Om du använder false eller någon annan sträng som argument kommer den att läsas som true.

Anledningen till att detta händer är att när type=xxx anges i add_argument() skickas argumentet till xxx().

Till exempel, om type=int skickas argumentet till int(); om type=float skickas det till float().

Samma sak gäller för type=bool, vilket innebär att argumentet skickas till bool().

Dom genom bool()

Denna bool() är en knepig fråga.

Följande värden betraktas som falska:

  • None
  • false
  • Noll i numeriska typer. Till exempel följande värden
    • 0
    • 0.0
    • 0j
  • En tom sekvens. Till exempel
    • ''
    • ()
    • []
  • Tom kartläggning. Till exempel
    • {}

Alla andra värden antas vara sanna – objekt av många typer är alltså alltid sanna. Operationer och inbyggda funktioner som returnerar boolska resultat returnerar alltid 0 eller False som det falska värdet och 1 eller True som det sanna värdet, om inget annat anges.

Därför kommer alla icke-tomma strängar som skickas till bool(), oavsett om de är ”sanna” eller ”falska”, att återge true. Endast tomma strängar blir falska.

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

print(bool(''))
# False

När type=bool anges i add_argument() skickas argumentet till bool(). Om false används som argument i exemplet ovan kommer bool() därför att omvandla det till strängen ”False” och läsa det som true, vilket visas i exemplet ovan.

Använd argumentåtgärden i stället för argumenttypen.

Om du vill använda boolska värden i argparse anger du ”store_true” eller ”store_false” för argumenthandlingen.

  • 'store_true'
  • 'store_false'

Dessa kommer att vara speciella versioner av ”store_const” som lagrar True respektive False. Dessutom kommer de att ställa in standardvärdena till False respektive True, i den ordningen.
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 det här exemplet ges följande alternativ.
--enOm en inte är inställd som true kommer den därför att laddas som false, vilket är standardvärdet för en.

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

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

Om du vill ställa in standardvärdet till true (sant) och false (falskt) när alternativet läggs till, gör du bara följande.
action='store_false'

Använda funktionen strtobool()

Om du vill använda positionella argument i stället för alternativ kan du också använda funktionen strtobool().

strtobool() är en funktion som omvandlar en sträng till sant (1) eller falskt (0).

Konverterar en boolsk sträng till sant (1) eller falskt (0).
De verkliga värdena är följande

  • y
  • yes
  • true
  • on
  • 1

Falska värden är följande.

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

Om val inte är någon av de ovan nämnda symbolerna uppstår ValueError.

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

Den är inte skiftlägeskänslig, så du kan till exempel använda följande; alla andra strängar kommer att resultera i ett fel.

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

Namnet är strtobool(), men returvärdet är inte bool, utan int (1 eller 0).

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

Som tidigare skrivits kommer argumentet att skickas till xxx() när type=xxx anges i add_argument() i argparse. Därför kan vi göra följande.
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ärdet är inte av typen bool, utan av typen int 1 eller 0, men den kan läsa sanna eller falska värden med true eller false som argument.

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

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

Om argumentet inte förväntas kommer ett fel att genereras 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