هنگام برخورد با مقادیر Boolean در argparse پایتون مراقب باشید

کسب و کار

برای مدیریت آرگومان های خط فرمان در پایتون، از ماژول های argv یا argparse ماژول sys استفاده کنید.

ماژول argparse امکان مدیریت انعطاف پذیر آرگومان های خط فرمان را فراهم می کند، اما هنگام برخورد با مقادیر بولی (درست، نادرست) باید مراقب بود.

اطلاعات زیر در اینجا ارائه شده است.

  • 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 را به عنوان نوع آرگومان add_argument() تعیین کنید، مانند int و float، آنطور که انتظار می رود کار نخواهد کرد.

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 به عنوان آرگومان استفاده شود، به عنوان یک نوع bool true خوانده می شود. این رفتار مورد انتظار است، اما مشکل در مورد زیر است.

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

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

اگر از false یا هر رشته دیگری به عنوان آرگومان استفاده کنید، درست خوانده می شود.

دلیل این اتفاق این است که وقتی type=xxx در add_argument() مشخص می شود، آرگومان به xxx() ارسال می شود.

به عنوان مثال، اگر type=int، آرگومان به int(); اگر type=float، سپس float().

این امر برای type=bool نیز صادق است، به این معنی که آرگومان به bool() ارسال خواهد شد.

قضاوت توسط bool()

این bool() مشکلی است.

مقادیر زیر نادرست در نظر گرفته می شوند:

  • None
  • false
  • صفر در انواع عددی. به عنوان مثال، مقادیر زیر
    • 0
    • 0
    • 0j
  • یک سکانس خالی مثلا
    • ()
    • []
  • نقشه برداری خالی مثلا
    • {}

همه مقادیر دیگر درست فرض می شوند – بنابراین اشیا از انواع مختلف همیشه درست هستند. عملیات و توابع داخلی که نتایج Boolean را برمی‌گردانند همیشه 0 یا False را به عنوان مقدار false و 1 یا True را به عنوان مقدار واقعی برمی‌گردانند، مگر اینکه خلاف آن ذکر شده باشد.

بنابراین، تمام رشته‌های غیر خالی ارسال شده به bool()، چه ‘true’ یا ‘false’، true برمی‌گردانند. فقط رشته های خالی نادرست خواهند بود.

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

اگر می‌خواهید پیش‌فرض را درست و زمانی که گزینه اضافه می‌شود، false قرار دهید، کافی است موارد زیر را انجام دهید.
action='store_false'

با استفاده از تابع strtobool()

اگر می خواهید به جای گزینه ها از آرگومان های موقعیتی استفاده کنید، می توانید از تابع strtobool() نیز استفاده کنید.

strtobool() تابعی است که یک رشته را به true (1) یا false (0) تبدیل می کند.

یک رشته بولی را به درست (1) یا نادرست (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'
Copied title and URL