Argparse: Các đối số bắt buộc được liệt kê trong các đối số tùy chọn của Wikipedia.


229

Tôi sử dụng mã đơn giản sau đây để phân tích một số đối số; lưu ý rằng một trong số họ là bắt buộc. Thật không may, khi người dùng chạy tập lệnh mà không cung cấp đối số, văn bản sử dụng / trợ giúp được hiển thị không cho biết rằng có một đối số không tùy chọn, điều mà tôi thấy rất khó hiểu. Làm cách nào tôi có thể lấy python để chỉ ra rằng một đối số không phải là tùy chọn?

Đây là mã:

import argparse
if __name__ == '__main__':
    parser = argparse.ArgumentParser(
        description='Foo')
    parser.add_argument('-i','--input', help='Input file name', required=True)
    parser.add_argument('-o','--output', help='Output file name', default="stdout")
    args = parser.parse_args()
    print ("Input file: %s" % args.input )
    print ("Output file: %s" % args.output )

Khi chạy mã ở trên mà không cung cấp đối số được yêu cầu, tôi nhận được kết quả đầu ra sau:

usage: foo.py [-h] -i INPUT [-o OUTPUT]

Foo

optional arguments:
    -h, --help            show this help message and exit
    -i INPUT, --input INPUT
                          Input file name
    -o OUTPUT, --output OUTPUT
                          Output file name

5
Trong dòng sử dụng, -i INPUTphần không được bao quanh bởi dấu ngoặc vuông, mà sự tinh tế chỉ ra rằng đó thực sự là bắt buộc. Ngoài ra, bạn có thể tự giải thích rằng thông qua các helpparam
Jaime RGP

7
@JaimeRGP Vâng, nhưng điều đó là không đủ, tất nhiên, và nó cũng ít hơn nổi bật. Tên nhóm được gán optional argumentscho các đối số được yêu cầu vẫn gây hiểu nhầm.
Acumenus

Câu trả lời:


316

Các thông số bắt đầu bằng -hoặc --thường được coi là tùy chọn. Tất cả các tham số khác là tham số vị trí và theo yêu cầu của thiết kế (như đối số chức năng vị trí). Có thể yêu cầu các đối số tùy chọn, nhưng điều này hơi trái với thiết kế của chúng. Vì chúng vẫn là một phần của các đối số không có vị trí, nên chúng vẫn sẽ được liệt kê dưới tiêu đề khó hiểu của các đối số tùy chọn, ngay cả khi chúng được yêu cầu. Tuy nhiên, dấu ngoặc vuông bị thiếu trong phần sử dụng cho thấy chúng thực sự cần thiết.

Xem thêm tài liệu :

Nói chung, mô-đun argparse giả định rằng các cờ như -f và --bar chỉ ra các đối số tùy chọn, luôn có thể được bỏ qua tại dòng lệnh.

Lưu ý: Các tùy chọn bắt buộc thường được coi là hình thức xấu vì người dùng mong đợi các tùy chọn là tùy chọn và do đó chúng nên được tránh khi có thể.

Điều đó đang được nói, các tiêu đề đối số Vị trí khác, các đối số tùy chọncác đối số tùy chọn, trong phần trợ giúp được tạo bởi hai nhóm đối số trong đó các đối số được tự động tách thành. Bây giờ, bạn có thể hack hack vào nó và thay đổi tên của những cái tùy chọn, nhưng một giải pháp thanh lịch hơn nhiều sẽ là tạo một nhóm khác cho Bắt buộc phải đặt tên là đối số tên lửa (hoặc bất cứ điều gì bạn muốn gọi chúng):

parser = argparse.ArgumentParser(description='Foo')
parser.add_argument('-o', '--output', help='Output file name', default='stdout')
requiredNamed = parser.add_argument_group('required named arguments')
requiredNamed.add_argument('-i', '--input', help='Input file name', required=True)
parser.parse_args(['-h'])
usage: [-h] [-o OUTPUT] -i INPUT

Foo

optional arguments:
  -h, --help            show this help message and exit
  -o OUTPUT, --output OUTPUT
                        Output file name

required named arguments:
  -i INPUT, --input INPUT
                        Input file name

Tôi đã có cùng một vấn đề. Tôi đã thử bạn giải pháp. Nó không thêm các đối số vào nhóm mới nhưng mã của tôi dường như không hoạt động sau đó. Bất kỳ giải pháp sẽ được đánh giá cao. Liên kết đến mã của tôi - pastebin.com/PvC2aujz
Zarar Mahmud

1
@ZararMahmud: Bạn đang chuyển các đối số trống trong dòng 24 của mã của mình: parser.parse_args([])Thay vào đó, hãy sử dụng parser.parse_args()không có đối số để nắm bắt nội dung của sys.argv. Per argparse
Devin

@poke: Giải pháp hay! Nhưng điều này không giúp ích gì trong trường hợp bạn cần các nhóm độc quyền lẫn nhau, hoặc tôi có thiếu điều gì không?
Thẩm phán

@Judge tôi khuyên bạn nên đọc pymotw.com/3/argparse/#mutual-exinating-options
Peter Moore

79

Vì tôi muốn liệt kê các đối số cần thiết trước khi tùy chọn, tôi hack xung quanh nó thông qua:

    parser = argparse.ArgumentParser()
    parser._action_groups.pop()
    required = parser.add_argument_group('required arguments')
    optional = parser.add_argument_group('optional arguments')
    required.add_argument('--required_arg', required=True)
    optional.add_argument('--optional_arg')
    return parser.parse_args()

và kết quả này:

usage: main.py [-h] [--required_arg REQUIRED_ARG]
               [--optional_arg OPTIONAL_ARG]

required arguments:
  --required_arg REQUIRED_ARG

optional arguments:
  --optional_arg OPTIONAL_ARG

Tôi có thể sống mà không có 'trợ giúp' hiển thị trong nhóm đối số tùy chọn.


3
Điều này thực sự buộc argparse phải đối xử với bất kỳ đối số nào theo yêu cầu?
Anthony

6
Tôi nghĩ rằng đối số 'bắt buộc' vẫn cần được đặt khi thêm đối số.
Karl Rosaen

Nó thật là tuyệt.
Paul Cezanne

7
@Anthony - không bạn cần 'required = True' trong add_argument cho điều đó. Câu trả lời trên chỉ minh họa nhóm lập luận.
dùng2275693

47

Xây dựng @Karl Rosaen

parser = argparse.ArgumentParser()
optional = parser._action_groups.pop() # Edited this line
required = parser.add_argument_group('required arguments')
# remove this line: optional = parser...
required.add_argument('--required_arg', required=True)
optional.add_argument('--optional_arg')
parser._action_groups.append(optional) # added this line
return parser.parse_args()

và kết quả này:

usage: main.py [-h] [--required_arg REQUIRED_ARG]
           [--optional_arg OPTIONAL_ARG]

required arguments:
  --required_arg REQUIRED_ARG

optional arguments:
  -h, --help                    show this help message and exit
  --optional_arg OPTIONAL_ARG

1
BTW, có cách nào để có quyền truy cập _action_groupmà không cần truy cập thành viên được bảo vệ không? Trong trường hợp của tôi, tôi cần thêm một số đối số vào nhóm (tùy chỉnh) đã tồn tại.
machin

Điều đó thật tuyệt. Giải quyết mục --help hiển thị trong danh sách tùy chọn thứ hai.
Jeremy

Lưu ý : câu trả lời này phá vỡ API bị lộ, kiểm tra câu trả lời của Bryan_D bên dưới.
lol

18

Một lần nữa, xây dựng @RalphyZ

Điều này không phá vỡ API tiếp xúc.

from argparse import ArgumentParser, SUPPRESS
# Disable default help
parser = ArgumentParser(add_help=False)
required = parser.add_argument_group('required arguments')
optional = parser.add_argument_group('optional arguments')

# Add back help 
optional.add_argument(
    '-h',
    '--help',
    action='help',
    default=SUPPRESS,
    help='show this help message and exit'
)
required.add_argument('--required_arg', required=True)
optional.add_argument('--optional_arg')

Điều này sẽ hiển thị giống như trên và sẽ tồn tại các phiên bản trong tương lai:

usage: main.py [-h] [--required_arg REQUIRED_ARG]
           [--optional_arg OPTIONAL_ARG]

required arguments:
  --required_arg REQUIRED_ARG

optional arguments:
  -h, --help                    show this help message and exit
  --optional_arg OPTIONAL_ARG

Bạn có thể giải thích câu trả lời của RalphyZ phá vỡ API bị lộ không?
jeremysprofile

5
_action_groupschỉ dành cho sử dụng nội bộ. Do đó, không có sự đảm bảo tương thích giữa các phiên bản.
Bryan_D
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.