อาร์กิวเมนต์: อาร์กิวเมนต์ที่จำเป็นแสดงรายการอยู่ภายใต้“ อาร์กิวเมนต์ที่เลือกได้” หรือไม่


229

ฉันใช้รหัสง่าย ๆ ต่อไปนี้เพื่อแยกอาร์กิวเมนต์บางอย่าง โปรดทราบว่าจำเป็นต้องใช้หนึ่งในนั้น น่าเสียดายที่เมื่อผู้ใช้รันสคริปต์โดยไม่ได้ระบุอาร์กิวเมนต์ข้อความการใช้งาน / ช่วยเหลือที่แสดงไม่ได้ระบุว่ามีอาร์กิวเมนต์ที่ไม่จำเป็นซึ่งฉันพบว่าสับสนมาก ฉันจะรับไพ ธ อนเพื่อระบุว่าการโต้แย้งนั้นไม่จำเป็นหรือไม่?

นี่คือรหัส:

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 )

เมื่อรันโค้ดข้างต้นโดยไม่ต้องระบุอาร์กิวเมนต์ที่ต้องการฉันจะได้ผลลัพธ์ต่อไปนี้:

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
ในสายการใช้งานชิ้น-i INPUTส่วนไม่ได้ล้อมรอบด้วยวงเล็บเหลี่ยมซึ่งความละเอียดบ่งบอกว่าจำเป็นจริง ๆ นอกจากนี้คุณสามารถอธิบายได้ด้วยตนเองผ่านhelpพารามิเตอร์
Jaime RGP

7
@ JaimeRGP ใช่ แต่ก็ไม่เพียงพอแน่นอนและมันก็ยังน้อยกว่าที่โดดเด่น ชื่อกลุ่มที่กำหนดoptional argumentsไว้สำหรับอาร์กิวเมนต์ที่จำเป็นยังคงทำให้เข้าใจผิด
คิวเมนตัส

คำตอบ:


316

พารามิเตอร์เริ่มต้นด้วย-หรือ--มักจะถือว่าเป็นตัวเลือก พารามิเตอร์อื่น ๆ ทั้งหมดเป็นพารามิเตอร์ตำแหน่งและตามที่ต้องการโดยการออกแบบ (เช่นอาร์กิวเมนต์ตำแหน่งฟังก์ชัน) เป็นไปได้ที่จะต้องมีอาร์กิวเมนต์ที่เป็นตัวเลือก แต่สิ่งนี้ขัดแย้งกับการออกแบบของพวกเขาเล็กน้อย เนื่องจากพวกเขายังคงเป็นส่วนหนึ่งของการขัดแย้งที่ไม่ใช่ตำแหน่งพวกเขาจะยังคงอยู่ภายใต้หัวข้อ "การมีตัวเลือกเสริม" ที่สับสนแม้ว่าพวกเขาจะต้อง เครื่องหมายวงเล็บเหลี่ยมที่ขาดหายไปในส่วนการใช้งานแสดงให้เห็นว่าจำเป็นต้องมี

ดูเอกสารประกอบ :

โดยทั่วไปโมดูล argparse จะถือว่าค่าสถานะเช่น -f และ --bar บ่งชี้ว่ามีอาร์กิวเมนต์ตัวเลือกซึ่งสามารถละเว้นได้ที่บรรทัดคำสั่ง

หมายเหตุ:ตัวเลือกที่จำเป็นโดยทั่วไปถือว่าเป็นรูปแบบที่ไม่ดีเนื่องจากผู้ใช้คาดหวังว่าตัวเลือกจะเป็นตัวเลือกและควรหลีกเลี่ยงเมื่อเป็นไปได้

ที่ถูกกล่าวว่าส่วนหัว"ข้อโต้แย้งตำแหน่ง"และ"ข้อโต้แย้งทางเลือก"ในความช่วยเหลือจะถูกสร้างขึ้นโดยกลุ่มอาร์กิวเมนต์สองกลุ่มซึ่งข้อโต้แย้งจะถูกแยกออกโดยอัตโนมัติ ตอนนี้คุณสามารถ“ แฮ็คมันได้” และเปลี่ยนชื่อของตัวเลือกเสริมได้ แต่วิธีแก้ปัญหาที่สง่างามกว่านั้นก็คือการสร้างกลุ่มอื่นสำหรับ

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

ฉันมีปัญหาเดียวกัน ฉันลองคุณทางออก มันเพิ่มการขัดแย้งในกลุ่มใหม่ แต่รหัสของฉันดูเหมือนจะไม่ทำงานหลังจากนั้น การแก้ปัญหาใด ๆ ที่จะได้รับการชื่นชม เชื่อมโยงไปยังรหัสของฉัน - pastebin.com/PvC2aujz
Zarar Mahmud

1
@ZararMahmud: คุณผ่านอาร์กิวเมนต์ว่างในบรรทัดที่ 24 ของรหัสของคุณ: parser.parse_args([])ให้ใช้parser.parse_args()โดยไม่มีอาร์กิวเมนต์เพื่อจับเนื้อหาของ sys.argv ต่อการโต้แย้ง
Devin

@poke: ทางออกที่ดี! แต่สิ่งนี้ไม่ได้ช่วยในกรณีที่คุณต้องการกลุ่มพิเศษร่วมกันหรือฉันไม่มีอะไรเลย?
ผู้พิพากษา

@ ผู้พิพากษาฉันอยากจะแนะนำให้อ่านpymotw.com/3/argparse/#mutually-exclusive-options
Peter Moore

79

เนื่องจากฉันต้องการแสดงรายการอาร์กิวเมนต์ที่ต้องการก่อนตัวเลือกฉันจึงแฮ็กมันผ่าน:

    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()

และผลลัพธ์นี้:

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

required arguments:
  --required_arg REQUIRED_ARG

optional arguments:
  --optional_arg OPTIONAL_ARG

ฉันสามารถอยู่ได้โดยปราศจาก 'ความช่วยเหลือ' แสดงในกลุ่มอาร์กิวเมนต์ที่เป็นทางเลือก


3
สิ่งนี้บังคับให้ผู้โต้แย้งโต้แย้งกับข้อโต้แย้งใด ๆ ตามที่ต้องการหรือไม่?
Anthony

6
ฉันคิดว่ายังจำเป็นต้องตั้งค่าอาร์กิวเมนต์ 'ต้อง' เมื่อเพิ่มอาร์กิวเมนต์
Karl Rosaen

นั่นเป็นสิ่งที่ดีจริงๆ
พอล Cezanne

7
@Anthony - คุณไม่จำเป็นต้องมี 'required = True' ใน add_argument สำหรับสิ่งนั้น คำตอบข้างต้นเป็นเพียงการจัดกลุ่มของอาร์กิวเมนต์
user2275693

47

อาคารนอกของ @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()

และผลลัพธ์นี้:

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 มีวิธีใดบ้าง (วิธี) ในการเข้าถึง_action_groupโดยไม่ต้องเข้าถึงสมาชิกที่ได้รับความคุ้มครอง ในกรณีของฉันฉันต้องเพิ่มอาร์กิวเมนต์บางอย่างไปยังกลุ่ม (กำหนดเอง) ที่มีอยู่แล้ว
แมชชีน

มันเยี่ยมมาก แก้ไขรายการ - ช่วยแสดงในรายการตัวเลือกที่สอง
Jeremy

หมายเหตุ : คำตอบนี้แบ่ง API ที่เปิดเผยตรวจสอบคำตอบโดย Bryan_Dด้านล่าง
lol

18

อีกครั้งหนึ่งที่สร้างจาก @RalphyZ

อันนี้ไม่ผิด API ที่เปิดเผย

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

ซึ่งจะแสดงเช่นเดียวกับด้านบนและควรอยู่รอดเวอร์ชันในอนาคต:

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

คุณช่วยอธิบายได้หรือไม่ว่าคำตอบของ RalphyZ แบ่ง API ที่เปิดเผยออกมาเป็นอย่างไร
jeremysprofile

5
_action_groupsมีไว้สำหรับใช้ภายในเท่านั้น ดังนั้นจึงไม่มีการรับประกันความเข้ากันได้ระหว่างเวอร์ชันต่าง ๆ
Bryan_D
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.