ระวังเมื่อจัดการกับค่าบูลีนในargparse .ของ Python

ธุรกิจ

ในการจัดการอาร์กิวเมนต์บรรทัดคำสั่งใน Python ให้ใช้โมดูล argv หรือ argparse ของโมดูล sys

โมดูล argparse ช่วยให้สามารถจัดการอาร์กิวเมนต์บรรทัดคำสั่งได้อย่างยืดหยุ่น แต่ต้องใช้ความระมัดระวังเมื่อจัดการกับค่าบูลีน (จริง เท็จ)

ข้อมูลต่อไปนี้มีให้ที่นี่

  • argparse สำหรับนิยามอาร์กิวเมนต์อย่างง่าย
  • ระบุประเภทของอาร์กิวเมนต์ (type) ด้วย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

ระบุประเภทของอาร์กิวเมนต์ (type) ด้วย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 ถูกใช้เป็นอาร์กิวเมนต์ ก็จะถูกอ่านว่าเป็น bool type true นี่เป็นลักษณะการทำงานที่คาดไว้ แต่ปัญหาคือกรณีต่อไปนี้

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

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

หากคุณใช้เท็จหรือสตริงอื่นใดเป็นอาร์กิวเมนต์ จะถูกอ่านว่าเป็นจริง

สาเหตุที่สิ่งนี้เกิดขึ้นคือเมื่อระบุ 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() ไม่ว่าจะเป็น ‘จริง’ หรือ ‘เท็จ’ จะส่งกลับค่าจริง เฉพาะสตริงว่างเท่านั้นที่จะเป็นเท็จ

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

print(bool(''))
# False

เมื่อตั้งค่า type=bool ใน add_argument() อาร์กิวเมนต์จะถูกส่งไปยัง bool() ดังนั้น ดังที่แสดงในตัวอย่างข้างต้น หากใช้ false เป็นอาร์กิวเมนต์ จะถูกแปลงโดย bool() เป็นสตริง ‘False’ และอ่านว่าเป็นจริง

ใช้การดำเนินการอาร์กิวเมนต์แทนประเภทอาร์กิวเมนต์

หากคุณต้องการใช้ค่าบูลีนใน argparse ให้ระบุ ‘store_true’ หรือ ‘store_false’ สำหรับการดำเนินการอาร์กิวเมนต์

  • store_true’
  • store_false’

สิ่งเหล่านี้จะเป็น ‘store_const’ รุ่นพิเศษที่จะจัดเก็บ True และ False ตามลำดับ นอกจากนี้ พวกเขาจะตั้งค่าเริ่มต้นเป็นเท็จและจริงตามลำดับ ตามลำดับนั้น
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 ไม่ถูกตั้งค่าเป็นจริง จะถูกโหลดเป็น 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() เป็นฟังก์ชันที่แปลงสตริงเป็นจริง (1) หรือเท็จ (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))

ค่าตอบแทนไม่ใช่ประเภทบูล แต่เป็น int ประเภท 1 หรือ 0 แต่สามารถอ่านค่าจริงหรือเท็จโดยมีค่าจริงหรือเท็จเป็นอาร์กิวเมนต์

$ 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