Hãy cẩn thận khi xử lý các giá trị Boolean trong argparse của Python

Kinh doanh

Để xử lý các đối số dòng lệnh trong Python, hãy sử dụng mô-đun argv hoặc argparse của mô-đun sys.

Mô-đun argparse cho phép xử lý linh hoạt các đối số dòng lệnh, nhưng phải cẩn thận khi xử lý các giá trị Boolean (true, false).

Thông tin sau được cung cấp ở đây.

  • cãi lại để dễ dàng định nghĩa các đối số
  • Chỉ định kiểu của đối số (kiểu) với argparse
  • Không chỉ định “bool” làm loại đối số của add_argument ()
  • Judgment by bool ()
  • Sử dụng hành động đối số thay vì loại đối số.
  • Sử dụng hàm strtobool ()

cãi lại để dễ dàng định nghĩa các đối số

Mô-đun argparse giúp dễ dàng xác định các đối số dòng lệnh.

Mô-đun argparse giúp dễ dàng tạo giao diện dòng lệnh thân thiện với người dùng. Bạn xác định những đối số mà chương trình của bạn cần, và argparse sẽ tìm ra cách phân tích cú pháp các tùy chọn đó từ sys.argv. mô-đun argparse tự động tạo thông báo trợ giúp và sử dụng, đồng thời phát sinh lỗi nếu người dùng chỉ định các đối số không hợp lệ cho chương trình. lỗi khi người dùng chỉ định các đối số không hợp lệ cho chương trình.
argparse — Parser for command-line options, arguments and sub-commands — Python 3.10.0 Documentation

Chỉ định kiểu của đối số (kiểu) với argparse

Một tính năng hữu ích của argparse là chỉ định kiểu (kiểu).

Ví dụ: nếu bạn chỉ định một kiểu số nguyên (int), nó sẽ tự động chuyển đổi đối số thành int và cũng phát sinh lỗi đối với các đối số không phải là int.

Kiểu được chỉ định bởi kiểu đối số của 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))

Chạy tệp này từ dòng lệnh.

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

Đối số 100 được đọc là int.

Nếu một giá trị không phải int được sử dụng làm đối số, thì sẽ xảy ra lỗi.

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

Rất hữu ích để chơi các cuộc tranh luận bất ngờ.

Không chỉ định “bool” làm loại đối số của add_argument ()

Điều quan trọng cần lưu ý là bool, như int và float, sẽ không hoạt động như mong đợi nếu bạn chỉ định bool làm kiểu đối số của 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))

Chạy tệp này từ dòng lệnh.

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

Nếu true được sử dụng làm đối số, nó sẽ được đọc là kiểu bool true. Đây là hành vi được mong đợi, nhưng vấn đề là trường hợp sau.

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

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

Nếu bạn sử dụng false hoặc bất kỳ chuỗi nào khác làm đối số, nó sẽ được đọc là true.

Lý do tại sao điều này xảy ra là khi type = xxx được chỉ định trong add_argument (), đối số được chuyển tới xxx ().

Ví dụ, nếu type = int, đối số sẽ được chuyển cho int (); nếu loại = float, sau đó float ().

Điều này cũng đúng với type = bool, có nghĩa là đối số sẽ được chuyển đến bool ().

Judgment by bool ()

Bool () này là một cái khó.

Các giá trị sau được coi là sai:

  • None
  • false
  • Số không trong các kiểu số. Ví dụ, các giá trị sau
    • 0
    • 0
    • 0j
  • Một chuỗi trống. Ví dụ
    • ()
    • []
  • Ánh xạ rỗng. Ví dụ
    • {}

Tất cả các giá trị khác được giả định là true – do đó các đối tượng thuộc nhiều loại luôn đúng. Các phép toán và hàm tích hợp trả về kết quả Boolean luôn trả về 0 hoặc False là giá trị sai và 1 hoặc True là giá trị đúng, trừ khi có ghi chú khác.

Do đó, tất cả các chuỗi không rỗng được chuyển đến bool (), cho dù là ‘true’ hay ‘false’, sẽ trả về true. Chỉ các chuỗi trống sẽ là sai.

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

print(bool(''))
# False

Khi type = bool được đặt trong add_argument (), đối số được chuyển cho bool (). Do đó, như thể hiện trong ví dụ trên, nếu false được sử dụng làm đối số, nó sẽ được chuyển đổi bởi bool () thành chuỗi ‘False’ và được đọc là true.

Sử dụng hành động đối số thay vì loại đối số.

Nếu bạn muốn sử dụng các giá trị Boolean trong argparse, hãy chỉ định ‘store_true’ hoặc ‘store_false’ cho hành động đối số.

  • store_true’
  • store_false’

Đây sẽ là các phiên bản đặc biệt của ‘store_const’ sẽ lưu trữ True và False tương ứng. Ngoài ra, họ sẽ đặt các giá trị mặc định tương ứng là Sai và Đúng theo thứ tự đó.
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))

Trong ví dụ này, các tùy chọn sau được đưa ra.
--enDo đó, nếu en không được đặt là true, nó sẽ được tải là false, đây là giá trị mặc định của en.

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

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

Nếu bạn muốn đặt mặc định thành true và false khi tùy chọn được thêm vào, chỉ cần thực hiện như sau.
action='store_false'

Sử dụng hàm strtobool ()

Nếu bạn muốn sử dụng các đối số vị trí thay vì các tùy chọn, bạn cũng có thể sử dụng hàm strtobool ().

strtobool () là một hàm chuyển đổi một chuỗi thành true (1) hoặc false (0).

Chuyển đổi một chuỗi boolean thành true (1) hoặc false (0).
Các giá trị thực như sau

  • y
  • yes
  • true
  • on
  • 1

Giá trị sai như sau.

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

Nếu val không phải là bất kỳ giá trị nào ở trên, nó sẽ làm tăng giá trị ValueError.

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

Nó không phân biệt chữ hoa chữ thường, vì vậy, ví dụ, bạn có thể sử dụng như sau; bất kỳ chuỗi nào khác sẽ dẫn đến lỗi.

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

Tên là strtobool (), nhưng giá trị trả về không phải là bool, mà là int (1 hoặc 0).

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

Như đã viết trước đó, khi type = xxx được chỉ định trong add_argument () của argparse, đối số sẽ được chuyển tới xxx (). Do đó, chúng ta có thể làm như sau.
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))

Giá trị trả về không phải là kiểu bool mà là kiểu int 1 hoặc 0, nhưng nó có thể đọc giá trị true hoặc false với true hoặc false dưới dạng đối số.

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

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

Ngoài ra, nếu đối số không được mong đợi, một lỗi sẽ được tạo đúng cách.

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