@Vikas द्वारा प्रदान किया गया समाधान उप-विशिष्ट-विशिष्ट वैकल्पिक तर्कों के लिए विफल रहता है, लेकिन दृष्टिकोण मान्य है। यहाँ एक बेहतर संस्करण है:
import argparse
parser = argparse.ArgumentParser(prog='PROG')
parser.add_argument('--foo', action='store_true', help='foo help')
subparsers = parser.add_subparsers(help='sub-command help', dest='subparser_name')
parser_a = subparsers.add_parser('command_a', help='command_a help')
parser_a.add_argument('bar', type=int, help='bar help')
parser_b = subparsers.add_parser('command_b', help='command_b help')
parser_b.add_argument('--baz', choices='XYZ', help='baz help')
argv = ['--foo', 'command_a', '12', 'command_b', '--baz', 'Z']
while argv:
print(argv)
options, argv = parser.parse_known_args(argv)
print(options)
if not options.subparser_name:
break
इसके parse_known_args
बजाय का उपयोग करता है parse_args
।parse_args
वर्तमान सबपर के लिए एक तर्क के रूप में जैसे ही गर्भपात का सामना करना पड़ता है, parse_known_args
उन्हें लौटाए गए ट्यूपल में दूसरे मूल्य के रूप में देता है। इस दृष्टिकोण में, शेष तर्कों को फिर से पार्सर को खिलाया जाता है। इसलिए प्रत्येक कमांड के लिए, एक नया नामस्पेस बनाया जाता है।
ध्यान दें कि इस मूल उदाहरण में, सभी वैश्विक विकल्प केवल पहले नाम Namespace में जोड़े जाते हैं, बाद के Namespaces के लिए नहीं।
यह दृष्टिकोण अधिकांश स्थितियों के लिए ठीक काम करता है, लेकिन इसकी तीन महत्वपूर्ण सीमाएँ हैं:
- अलग-अलग उप-क्षेत्रों के लिए एक ही वैकल्पिक तर्क का उपयोग करना संभव नहीं है, जैसे
myprog.py command_a --foo=bar command_b --foo=bar
।
- यह subcommands (के साथ किसी भी चर लंबाई स्थितीय तर्क का उपयोग करने के लिए संभव नहीं है
nargs='?'
या nargs='+'
या nargs='*'
)।
- किसी भी ज्ञात तर्क को नए आदेश पर 'ब्रेकिंग' के बिना, पार्स किया जाता है। उदाहरण में
PROG --foo command_b command_a --baz Z 12
ऊपर कोड के साथ, --baz Z
से भस्म हो जाएगा command_b
, नहीं द्वाराcommand_a
।
ये सीमाएँ एक सीमित सीमा का विवाद हैं। यहाँ एक सरल उदाहरण दिया गया है जो एकल उपकमांड का उपयोग करते समय argparse -even की सीमाओं को दर्शाता है-
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('spam', nargs='?')
subparsers = parser.add_subparsers(help='sub-command help', dest='subparser_name')
parser_a = subparsers.add_parser('command_a', help='command_a help')
parser_a.add_argument('bar', type=int, help='bar help')
parser_b = subparsers.add_parser('command_b', help='command_b help')
options = parser.parse_args('command_a 42'.split())
print(options)
यह बढ़ा देगा error: argument subparser_name: invalid choice: '42' (choose from 'command_a', 'command_b')
।
कारण यह है कि आंतरिक विधि argparse.ArgParser._parse_known_args()
बहुत लालची है और मानती है कि command_a
वैकल्पिक spam
तर्क का मूल्य है । विशेष रूप से, जब वैकल्पिक और स्थिति संबंधी तर्कों को 'विभाजित' करते हैं, तो तर्क _parse_known_args()
के नामों (जैसे command_a
या command_b
) को नहीं देखते हैं, लेकिन केवल वे जहां तर्क सूची में होते हैं। यह भी मान लिया गया है कि कोई भी उपकमांड शेष सभी तर्कों का उपभोग करेगा। argparse
मल्टी-कमांड सबपर्सर्स के समुचित कार्यान्वयन को भी रोकता है। दुर्भाग्य से इसका मतलब है कि एक उचित कार्यान्वयन के लिए एक पूर्ण पुनर्लेखन की आवश्यकता हैargparse.ArgParser._parse_known_args()
विधि के , जो कोड की 200+ पंक्तियाँ होती हैं।
इन सीमाओं को देखते हुए, यह केवल एक विकल्प हो सकता है कि सब-कमैंड के बजाय एक ही बहु-विकल्प तर्क पर वापस लौटें:
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('--bar', type=int, help='bar help')
parser.add_argument('commands', nargs='*', metavar='COMMAND',
choices=['command_a', 'command_b'])
options = parser.parse_args('--bar 2 command_a command_b'.split())
print(options)
उपयोग जानकारी में विभिन्न आदेशों को सूचीबद्ध करना संभव है, मेरा उत्तर https://stackoverflow.com/a/49999185/428542 देखें