Bądź ostrożny, gdy masz do czynienia z wartościami logicznymi w argparse Pythona

Biznes

Aby obsłużyć argumenty wiersza poleceń w Pythonie, należy użyć modułów argv lub argparse modułu sys.

Moduł argparse pozwala na elastyczną obsługę argumentów wiersza poleceń, ale należy zachować ostrożność, gdy mamy do czynienia z wartościami logicznymi (true, false).

Podane są tu następujące informacje.

  • argparse dla łatwego definiowania argumentów
  • Określ typ argumentu (type) za pomocą argparse
  • Nie określaj „bool” jako typ argumentu funkcji add_argument()
  • Wyrok przez bool()
  • Użyj akcji argumentu zamiast typu argumentu.
  • Użycie funkcji strtobool()

argparse dla łatwego definiowania argumentów

Moduł argparse ułatwia definiowanie argumentów wiersza poleceń.

Moduł argparse ułatwia tworzenie przyjaznych dla użytkownika interfejsów wiersza poleceń. Określasz, jakich argumentów potrzebuje twój program, a moduł argparse wymyśli, jak przetworzyć te opcje z pliku sys.argv. Moduł argparse automatycznie generuje pomoc i komunikaty o użyciu oraz podnosi błąd, jeśli użytkownik poda nieprawidłowe argumenty do programu. błąd, jeśli użytkownik poda nieprawidłowe argumenty do programu.
argparse — Parser for command-line options, arguments and sub-commands — Python 3.10.0 Documentation

Określ typ argumentu (type) za pomocą argparse

Przydatną cechą argparse jest możliwość określenia typu (type).

Na przykład, jeśli podasz typ integer (int), automatycznie przekonwertuje on argument na int, a także podniesie błąd dla argumentów, które nie są int.

Typ jest określony przez typ argumentu funkcji 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))

Uruchom ten plik z wiersza poleceń.

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

Argument 100 jest odczytywany jako int.

Jeśli jako argument zostanie użyta wartość inna niż liczba całkowita, wystąpi błąd.

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

Bardzo przydatny do rozgrywania nieoczekiwanych argumentów.

Nie określaj „bool” jako typ argumentu funkcji add_argument()

Ważne jest, aby zauważyć, że bool, podobnie jak int i float, nie będzie działał zgodnie z oczekiwaniami, jeśli podasz bool jako typ argumentu funkcji 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))

Uruchom ten plik z wiersza poleceń.

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

Jeśli jako argument zostanie użyty true, zostanie on odczytany jako bool typu true. Jest to oczekiwane zachowanie, ale problem pojawia się w następującym przypadku.

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

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

Jeśli jako argumentu użyjesz false lub jakiegokolwiek innego ciągu znaków, zostanie on odczytany jako true.

Powodem, dla którego tak się dzieje jest to, że gdy typ=xxx jest określony w add_argument(), argument jest przekazywany do xxx().

Na przykład, jeśli typ=int, to argument zostanie przekazany do int(); jeśli typ=float, to do float().

To samo jest prawdziwe dla type=bool, co oznacza, że argument zostanie przekazany do funkcji bool().

Wyrok przez bool()

Ta funkcja bool() jest podchwytliwa.

Następujące wartości są uważane za fałszywe:

  • None
  • false
  • Zero w typach numerycznych. Na przykład, następujące wartości
    • 0
    • 0.0
    • 0j
  • Pusta sekwencja. Na przykład
    • ''
    • ()
    • []
  • Puste mapowanie. Na przykład
    • {}

Wszystkie inne wartości są uważane za prawdziwe – dlatego obiekty wielu typów są zawsze prawdziwe. Operacje i funkcje wbudowane, które zwracają wyniki Boolean zawsze zwracają 0 lub False jako wartość false i 1 lub True jako wartość true, chyba że zaznaczono inaczej.

Dlatego wszystkie niepuste łańcuchy przekazane do bool(), niezależnie od tego czy są 'true' czy 'false', zwrócą true. Tylko puste łańcuchy będą fałszywe.

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

print(bool(''))
# False

Kiedy typ=bool jest ustawiony w add_argument(), argument jest przekazywany do funkcji bool(). Dlatego, jak pokazano w powyższym przykładzie, jeśli jako argument zostanie użyty false, zostanie on przekonwertowany przez bool() jako łańcuch 'False' i odczytany jako true.

Użyj akcji argumentu zamiast typu argumentu.

Jeśli chcesz używać wartości logicznych w argparse, podaj 'store_true' lub 'store_false' dla akcji argumentu.

  • 'store_true'
  • 'store_false'

Będą to specjalne wersje 'store_const', które będą przechowywać odpowiednio True i False. Dodatkowo, będą one ustawiać wartości domyślne na False i True, w tej kolejności.
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))

W tym przykładzie podane są następujące opcje.
--enDlatego, jeśli en nie jest ustawione jako true, zostanie załadowane jako false, co jest wartością domyślną en.

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

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

Jeśli chcesz ustawić domyślną wartość na true, a po dodaniu opcji na false, wykonaj następujące czynności.
action='store_false'

Użycie funkcji strtobool()

Jeśli chcesz użyć argumentów pozycyjnych zamiast opcji, możesz również użyć funkcji strtobool().

strtobool() jest funkcją, która konwertuje ciąg znaków na wartość true (1) lub false (0).

Konwertuje łańcuch boolean na true (1) lub false (0).
Prawdziwe wartości są następujące

  • y
  • yes
  • true
  • on
  • 1

Fałszywe wartości są następujące.

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

Jeśli val nie jest żadnym z powyższych, podnosi ValueError.

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

Nie jest rozróżniana wielkość liter, więc na przykład, możesz użyć następującego; każdy inny łańcuch spowoduje błąd.

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

Nazywa się strtobool(), ale zwracaną wartością nie jest bool, ale int (1 lub 0).

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

Jak napisano wcześniej, gdy typ=xxx zostanie podany w add_argument() argparse, argument zostanie przekazany do xxx(). W związku z tym, możemy zrobić co następuje.
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))

Wartość zwracana nie jest typu bool, ale typu int 1 lub 0, ale może odczytywać wartości true lub false z true lub false jako argumentami.

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

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

Ponadto, jeśli argument nie jest oczekiwany, błąd zostanie wygenerowany prawidłowo.

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