Giới thiệu
Khi viết chương trình dòng lệnh (CLI) với argparse, thường cần giới hạn giá trị người dùng có thể nhập cho một đối số. Ví dụ: số lượng Grand Slam titles của cầu thủ tennis chỉ từ 0 đến 20 (tính đến 2020).
Vấn đề: Chưa giới hạn giá trị
import argparse
def get_args():
parser = argparse.ArgumentParser(
description='Ví dụ đối số vị trí',
formatter_class=argparse.ArgumentDefaultsHelpFormatter
)
parser.add_argument('titles', metavar='titles', type=int, help='Số GrandSlam titles')
return parser.parse_args()
def main(titles):
print(f"*** Cầu thủ đã thắng {titles} GrandSlam titles.")
if __name__ == '__main__':
args = get_args()
main(args.titles)
Chạy thử:
$ python test.py 20 *** Cầu thủ đã thắng 20 GrandSlam titles. $ python test.py 50 *** Cầu thủ đã thắng 50 GrandSlam titles. ← Sai logic! $ python test.py -1 *** Cầu thủ đã thắng -1 GrandSlam titles. ← Sai logic!
Giải pháp: Sử dụng tham số choices
Tham số choices nhận một iterable (list, range, tuple...) chứa các giá trị hợp lệ. argparse sẽ tự động kiểm tra và báo lỗi nếu giá trị nhập vào không nằm trong danh sách.
import argparse
def get_args():
parser = argparse.ArgumentParser(
description='Ví dụ đối số vị trí với choices',
formatter_class=argparse.ArgumentDefaultsHelpFormatter
)
# Giới hạn titles từ 0 đến 19 (range(0, 20) không bao gồm 20)
parser.add_argument('titles', metavar='titles', type=int,
choices=range(0, 20), help='GrandSlam Titles (0-19)')
return parser.parse_args()
def main(titles):
print(f"*** Cầu thủ đã thắng {titles} GrandSlam titles.")
if __name__ == '__main__':
args = get_args()
main(args.titles)
Kết quả
$ python test.py 30 usage: test.py [-h] titles test.py: error: argument titles: invalid choice: 30 (choose from 0, 1, 2, ..., 19) $ python test.py 10 *** Cầu thủ đã thắng 10 GrandSlam titles. $ python test.py -1 usage: test.py [-h] titles test.py: error: argument titles: invalid choice: -1 (choose from 0, 1, 2, ..., 19) $ python test.py 0 *** Cầu thủ đã thắng 0 GrandSlam titles. $ python test.py 20 usage: test.py [-h] titles test.py: error: argument titles: invalid choice: 20 (choose from 0, 1, 2, ..., 19)
Kết hợp với đối số chuỗi (string choices)
import argparse
def get_args():
parser = argparse.ArgumentParser(
description='Ví dụ nhiều đối số với choices',
formatter_class=argparse.ArgumentDefaultsHelpFormatter
)
parser.add_argument('player', metavar='player', type=str,
choices=['federer', 'nadal', 'djokovic'],
help='Tennis Players')
parser.add_argument('titles', metavar='titles', type=int,
choices=range(0, 20),
help='GrandSlam Titles')
return parser.parse_args()
def main(player, titles):
print(f"*** {player} đã thắng {titles} GrandSlam titles.")
if __name__ == '__main__':
args = get_args()
main(args.player, args.titles)
$ python test.py "djokovic" 17 *** djokovic đã thắng 17 GrandSlam titles. $ python test.py "murray" 5 usage: test.py [-h] player titles test.py: error: argument player: invalid choice: 'murray' (choose from 'federer', 'nadal', 'djokovic')
Tóm tắt
choicesnhận list/tuple/range các giá trị hợp lệ.argparsetự động validate và hiển thị danh sách lựa chọn khi lỗi.- Áp dụng được cho cả kiểu
int,strvà các kiểu khác. - Giúp tăng tính robust cho CLI mà không cần viết code kiểm tra thủ công.