Будьте обережні, коли маєте справу з логічними значеннями в argparse Python

Бізнес

Для обробки аргументів командного рядка в Python використовуйте модулі argv або argparse модуля sys.

Модуль argparse дозволяє гнучко обробляти аргументи командного рядка, але при роботі з булевими значеннями (true, false) слід бути обережними.

Наведена нижче інформація.

  • argparse для легкого визначення аргументів
  • Вкажіть тип аргументу (тип) за допомогою argparse
  • Не вказуйте “bool” як тип аргументу add_argument()
  • Судження за bool()
  • Використовуйте дію аргументу замість типу аргументу.
  • Використання функції strtobool().

argparse для легкого визначення аргументів

Модуль argparse дозволяє легко визначати аргументи командного рядка.

Модуль argparse дозволяє легко створювати зручні інтерфейси командного рядка. Ви визначаєте, які аргументи потрібні вашій програмі, і argparse зрозуміє, як розібрати ці параметри з sys.argv. Модуль argparse автоматично генерує повідомлення довідки та використання, а також викликає помилку, якщо користувач вказує недійсні аргументи для програми. помилка, коли користувач вказує недійсні аргументи для програми.
argparse — Parser for command-line options, arguments and sub-commands — Python 3.10.0 Documentation

Вкажіть тип аргументу (тип) за допомогою argparse

Корисною особливістю argparse є визначення типу (типу).

Наприклад, якщо ви вкажете цілочисельний тип (int), він автоматично перетворить аргумент у int, а також викличе помилку для аргументів, які не є int.

Тип визначається типом аргументу 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))

Запустіть цей файл із командного рядка.

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

Аргумент 100 читається як int.

Якщо в якості аргументу використовується значення, відмінне від int, виникне помилка.

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

Дуже корисно для відтворення несподіваних аргументів.

Не вказуйте “bool” як тип аргументу add_argument()

Важливо зауважити, що bool, як і int і float, не працюватимуть належним чином, якщо ви вкажете bool як тип аргументу 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))

Запустіть цей файл із командного рядка.

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

Якщо в якості аргументу використовується true, він буде прочитаний як логічний тип true. Це очікувана поведінка, але проблема полягає в наступному випадку.

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

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

Якщо ви використовуєте false або будь-який інший рядок як аргумент, він буде прочитаний як true.

Причина, чому це відбувається, полягає в тому, що коли type=xxx вказано в add_argument(), аргумент передається xxx().

Наприклад, якщо type=int, аргумент буде передано до int(); якщо type=float, то float().

Те ж саме вірно для type=bool, що означає, що аргумент буде переданий до bool().

Судження за bool()

Цей bool() є складним.

Наступні значення вважаються хибними:

  • None
  • false
  • Нуль у числових типах. Наприклад, наступні значення
    • 0
    • 0
    • 0j
  • Порожня послідовність. Наприклад
    • ()
    • []
  • Порожнє відображення. Наприклад
    • {}

Усі інші значення вважаються істинними, тому об’єкти багатьох типів завжди є істинними. Операції та вбудовані функції, які повертають логічні результати, завжди повертають 0 або False як хибне значення і 1 або True як істинне значення, якщо не вказано інше.

Таким чином, усі непорожні рядки, передані до bool(), незалежно від того, чи є «true» чи «false», повертатимуть true. Тільки порожні рядки будуть false.

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

print(bool(''))
# False

Коли type=bool встановлено в add_argument(), аргумент передається до bool(). Тому, як показано у прикладі вище, якщо false використовувати як аргумент, він буде перетворений за допомогою bool() як рядок ‘False’ і прочитаний як true.

Використовуйте дію аргументу замість типу аргументу.

Якщо ви хочете використовувати логічні значення в argparse, вкажіть ‘store_true’ або ‘store_false’ для дії аргументу.

  • store_true’
  • store_false’

Це будуть спеціальні версії ‘store_const’, які зберігатимуть True і False відповідно. Крім того, вони встановлять значення за замовчуванням на False і True відповідно, у цьому порядку.
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))

У цьому прикладі наведені наступні варіанти.
--enТому, якщо en не встановлено як true, він буде завантажений як false, що є значенням en за замовчуванням.

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

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

Якщо ви хочете встановити значення за замовчуванням як true і false, коли додається параметр, просто виконайте наступне.
action='store_false'

Використання функції strtobool().

Якщо ви хочете використовувати позиційні аргументи замість параметрів, ви також можете використовувати функцію strtobool().

strtobool() — це функція, яка перетворює рядок у true (1) або false (0).

Перетворює логічний рядок у true (1) або false (0).
Справжні значення такі

  • y
  • yes
  • true
  • on
  • 1

Помилкові значення такі.

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

Якщо val не є жодним із перерахованих вище, він викликає ValueError.

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

Він не чутливий до регістру, тому, наприклад, ви можете використовувати наступне; будь-який інший рядок призведе до помилки.

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

Ім’я – strtobool(), але повертається значення не bool, а int (1 або 0).

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

Як було написано раніше, коли type=xxx вказано в add_argument() argparse, аргумент буде передано до xxx(). Тому ми можемо зробити наступне.
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))

Повертається значення не є типом bool, а типом int 1 або 0, але воно може читати значення true або false з аргументами true або false.

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

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

Крім того, якщо аргумент не очікується, помилка буде створена належним чином.

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