कैसे अजगर argparse का उपयोग कर कई नेस्टेड उप-कमान पार्स करने के लिए?


82

मैं एक कमांड लाइन कार्यक्रम लागू कर रहा हूं जिसमें इस तरह का इंटरफ़ेस है:

cmd [GLOBAL_OPTIONS] {command [COMMAND_OPTS]} [{command [COMMAND_OPTS]} ...]

मैं अर्गपर्स डॉक्यूमेंटेशन से गुजरा हूं । मैं लागू कर सकते हैं GLOBAL_OPTIONSका उपयोग कर वैकल्पिक तर्क के रूप में add_argumentमें argparse। और उप-कमांड{command [COMMAND_OPTS]} का उपयोग करना ।

प्रलेखन से ऐसा लगता है कि मेरे पास केवल एक उप-कमान हो सकता है। लेकिन जैसा कि आप देख सकते हैं कि मुझे एक या एक से अधिक उप-आदेशों को लागू करना होगा। ऐसे कमांड लाइन तर्कों का उपयोग करने का सबसे अच्छा तरीका क्या है argparse?


2
मुझे नहीं लगता कि यह वही है जिसके लिए उप-कमांड का इरादा है। प्रलेखन से यह बताता है कि यह अलग-अलग उपप्रोग्राम को नियंत्रित करने के लिए संक्षेप में है । क्या आपने तर्क समूहों में देखा है ?
क्रिस

डिस्टुटिल्स ./setup.pyमें यह शैली सीएलआई इंटरफ़ेस भी है, उनके स्रोत कोड को देखना दिलचस्प होगा।
सिरो सांटिल्ली 郝海东 冠状 i 法轮功 ''

जवाबों:


27

मैं उसी भाव के साथ आया हूं, और ऐसा लगता है कि मुझे बेहतर उत्तर मिला है।

इसका समाधान यह है कि हम किसी दूसरे सबपर के साथ बस उप-पादरी का घोंसला नहीं बना सकते हैं, लेकिन हम दूसरे सबपर के बाद एक पार्सर के साथ सबपर को जोड़ सकते हैं।

कोड आपको बताता है:

parent_parser = argparse.ArgumentParser(add_help=False)                                                                                                  
parent_parser.add_argument('--user', '-u',                                                                                                               
                    default=getpass.getuser(),                                                                                                           
                    help='username')                                                                                                                     
parent_parser.add_argument('--debug', default=False, required=False,                                                                                     
                           action='store_true', dest="debug", help='debug flag')                                                                         
main_parser = argparse.ArgumentParser()                                                                                                                  
service_subparsers = main_parser.add_subparsers(title="service",                                                                                         
                    dest="service_command")                                                                                                              
service_parser = service_subparsers.add_parser("first", help="first",                                                                                    
                    parents=[parent_parser])                                                                                                             
action_subparser = service_parser.add_subparsers(title="action",                                                                                         
                    dest="action_command")                                                                                                               
action_parser = action_subparser.add_parser("second", help="second",                                                                                     
                    parents=[parent_parser])                                                                                                             

args = main_parser.parse_args()   

हां, argparseनेस्टेड सबपर्सर्स की अनुमति देता है। लेकिन मैंने उन्हें केवल एक अन्य स्थान पर इस्तेमाल किया है - एक पायथन मुद्दे के लिए एक परीक्षण मामले में, Bugs.python.org/issue14365
hpaulj

9
यह मानता है कि आदेशों में एक नेस्टेड संरचना है। लेकिन सवाल "समांतर" आदेश के लिए पूछ रहा है
augurar

25

@mgilson के पास इस सवाल का एक अच्छा जवाब है। लेकिन खुद sys.argv को विभाजित करने में समस्या यह है कि मैं उपयोगकर्ता के लिए सभी अच्छे मदद संदेश खो देता हूं। इसलिए मैंने यह करना समाप्त कर दिया:

import argparse

## This function takes the 'extra' attribute from global namespace and re-parses it to create separate namespaces for all other chained commands.
def parse_extra (parser, namespace):
  namespaces = []
  extra = namespace.extra
  while extra:
    n = parser.parse_args(extra)
    extra = n.extra
    namespaces.append(n)

  return namespaces

argparser=argparse.ArgumentParser()
subparsers = argparser.add_subparsers(help='sub-command help', dest='subparser_name')

parser_a = subparsers.add_parser('command_a', help = "command_a help")
## Setup options for parser_a

## Add nargs="*" for zero or more other commands
argparser.add_argument('extra', nargs = "*", help = 'Other commands')

## Do similar stuff for other sub-parsers

अब पहले पार्स के बाद सभी जंजीरों में जमा हो जाती है extra। मैं इसे फिर से लागू करता हूं, जबकि सभी जंजीरों को प्राप्त करने और उनके लिए अलग नामस्थान बनाने के लिए यह खाली नहीं है। और मुझे अच्छा उपयोग स्ट्रिंग मिलता है जो उत्पन्न होता है।


2
@Flavius, के बाद मैं namespaceफोन करके पार्सर से namespace = argparser.parse_args(), मैं फोन parse_extraके साथ parserऔर namespaceextra_namespaces = parse_extra( argparser, namespace )
विकास

मुझे लगता है कि मैं तर्क को समझता हूं, लेकिन parserआपके पास कोड में क्या है । मैं केवल extraतर्क को जोड़ने के लिए इसका उपयोग करता हुआ देखता हूं । फिर आपने उपरोक्त टिप्पणी में फिर से इसका उल्लेख किया। क्या यह माना जाता है argparser?
jmlopez

@jmlopez हाँ यह होना चाहिए argparser। इसे संपादित करेंगे।
विकास

1
ध्यान दें कि यह समाधान उप-विशिष्ट-विशिष्ट वैकल्पिक तर्कों के लिए विफल रहता है। वैकल्पिक समाधान के लिए मेरा समाधान नीचे देखें ( stackoverflow.com/a/49977713/428542 )।
मैकफ्रिक

1
यहाँ एक उदाहरण है कि यह कैसे विफल होता है। निम्नलिखित 3 पंक्तियाँ जोड़ें parser_b = subparsers.add_parser('command_b', help='command_b help'):; parser_b.add_argument('--baz', choices='XYZ', help='baz help'); options = argparser.parse_args(['--foo', 'command_a', 'command_b', '--baz', 'Z']); यह एक त्रुटि के साथ विफल हो जाता है PROG: error: unrecognized arguments: --baz Z। इसका कारण यह है कि के पार्सिंग के दौरान command_a, command_bपहले से ही पार्स किए गए वैकल्पिक तर्क (और सबपर के लिए अज्ञात हैं command_a)।
मैकफ्रीक

14

parse_known_argsएक नामस्थान और अज्ञात तारों की एक सूची देता है। यह extraचेक किए गए उत्तर में समान है ।

import argparse
parser = argparse.ArgumentParser()
parser.add_argument('--foo')
sub = parser.add_subparsers()
for i in range(1,4):
    sp = sub.add_parser('cmd%i'%i)
    sp.add_argument('--foo%i'%i) # optionals have to be distinct

rest = '--foo 0 cmd2 --foo2 2 cmd3 --foo3 3 cmd1 --foo1 1'.split() # or sys.argv
args = argparse.Namespace()
while rest:
    args,rest =  parser.parse_known_args(rest,namespace=args)
    print args, rest

उत्पादन:

Namespace(foo='0', foo2='2') ['cmd3', '--foo3', '3', 'cmd1', '--foo1', '1']
Namespace(foo='0', foo2='2', foo3='3') ['cmd1', '--foo1', '1']
Namespace(foo='0', foo1='1', foo2='2', foo3='3') []

एक वैकल्पिक लूप प्रत्येक सबपर को अपना नामस्थान देगा। यह स्थिति नामों में ओवरलैप की अनुमति देता है।

argslist = []
while rest:
    args,rest =  parser.parse_known_args(rest)
    argslist.append(args)

अच्छी तरह से काम करता है। हालांकि एक दोष है: यदि कहीं एक गलत वर्तनी विकल्प है (उदाहरण के लिए rest = '--foo 0 cmd2 --foo2 2 --bar cmd3 --foo3 3 cmd1 --foo1 1'.split()), तो error: too few argumentsअमान्य विकल्प को इंगित करने के बजाय, समाप्त हो जाएगा । इसका कारण यह है कि खराब विकल्प को restतब तक छोड़ दिया जाएगा जब तक हम कमांड के तर्क से बाहर नहीं हो जाते।
एड्रियन डब्ल्यू

टिप्पणी # or sys.argvहोनी चाहिए # or sys.argv[1:]
एड्रियन डब्ल्यू

5

आप हमेशा कमांड-लाइन को स्वयं विभाजित कर सकते हैं ( sys.argvअपने कमांड नामों पर विभाजित करें), और उसके बाद केवल विशेष कमांड के अनुरूप भाग को पास करें parse_args- आप चाहें Namespaceतो नेमस्पेस कीवर्ड का उपयोग करके भी इसका उपयोग कर सकते हैं।

कमांडलाइन को समूहीकृत करना आसान है itertools.groupby:

import sys
import itertools
import argparse    

mycommands=['cmd1','cmd2','cmd3']

def groupargs(arg,currentarg=[None]):
    if(arg in mycommands):currentarg[0]=arg
    return currentarg[0]

commandlines=[list(args) for cmd,args in intertools.groupby(sys.argv,groupargs)]

#setup parser here...
parser=argparse.ArgumentParser()
#...

namespace=argparse.Namespace()
for cmdline in commandlines:
    parser.parse_args(cmdline,namespace=namespace)

#Now do something with namespace...

अपरीक्षित


1
धन्यवाद mgilson। यह मेरे प्रश्न का एक अच्छा समाधान है, लेकिन मैंने इसे थोड़ा अलग तरीके से पूरा किया। मैंने एक और जवाब जोड़ा ।
विकास

1
का अच्छा उपयोग itertools.groupby()! इससे पहले कि मैं जानता था कि मैंने ऐसा ही किया है groupby()
केज़ापाकोव

5

@Mgilson द्वारा उत्तर पर सुधार करते हुए, मैंने एक छोटी सी पार्सिंग विधि लिखी जो भागों में विभाजित होती है और कमांडों के तर्कों को नामस्थानों के पदानुक्रम में डालती है:

import sys
import argparse


def parse_args(parser, commands):
    # Divide argv by commands
    split_argv = [[]]
    for c in sys.argv[1:]:
        if c in commands.choices:
            split_argv.append([c])
        else:
            split_argv[-1].append(c)
    # Initialize namespace
    args = argparse.Namespace()
    for c in commands.choices:
        setattr(args, c, None)
    # Parse each command
    parser.parse_args(split_argv[0], namespace=args)  # Without command
    for argv in split_argv[1:]:  # Commands
        n = argparse.Namespace()
        setattr(args, argv[0], n)
        parser.parse_args(argv, namespace=n)
    return args


parser = argparse.ArgumentParser()
commands = parser.add_subparsers(title='sub-commands')

cmd1_parser = commands.add_parser('cmd1')
cmd1_parser.add_argument('--foo')

cmd2_parser = commands.add_parser('cmd2')
cmd2_parser.add_argument('--foo')

cmd2_parser = commands.add_parser('cmd3')
cmd2_parser.add_argument('--foo')


args = parse_args(parser, commands)
print(args)

यह अच्छी तरह से व्यवहार करता है, अच्छी सहायता प्रदान करता है:

के लिये ./test.py --help :

usage: test.py [-h] {cmd1,cmd2,cmd3} ...

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

sub-commands:
  {cmd1,cmd2,cmd3}

के लिये ./test.py cmd1 --help :

usage: test.py cmd1 [-h] [--foo FOO]

optional arguments:
  -h, --help  show this help message and exit
  --foo FOO

और तर्क मानों वाले नामस्थानों का एक पदानुक्रम बनाता है:

./test.py cmd1 --foo 3 cmd3 --foo 4
Namespace(cmd1=Namespace(foo='3'), cmd2=None, cmd3=Namespace(foo='4'))

ऊपर आपके कोड की समीक्षा करते हुए, मैं एक समस्या में भाग गया। लाइन 18 पर, आप का उल्लेख split_argv[0]जो वास्तव में खाली है split_argv, क्योंकि आप संलग्न [c]करने के लिए split_argv(शुरू में करने के लिए सेट [[]])। यदि आप 7 से लाइन बदलते हैं split_argv = [], तो सब कुछ अपेक्षित रूप से काम करता है।
HEADLESS_0NE

2
मैं कोड आप साझा करने के लिए कुछ और सुधारों (फिर से) किया था और इस के साथ समाप्त हो गया (कुछ मुद्दों पर मैं में चल रहा था फिक्सिंग): gist.github.com/anonymous/f4be805fc3ff9e132eb1e1aa0b4f7d4b
HEADLESS_0NE

यह उत्तर बहुत अच्छा है, आप यह निर्धारित कर सकते हैं कि विधि stackoverflow.com/questions/8250010/… परsubparseradd_subparsers
भाग्य

5

@Vikas द्वारा प्रदान किया गया समाधान उप-विशिष्ट-विशिष्ट वैकल्पिक तर्कों के लिए विफल रहता है, लेकिन दृष्टिकोण मान्य है। यहाँ एक बेहतर संस्करण है:

import argparse

# create the top-level parser
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')

# create the parser for the "command_a" command
parser_a = subparsers.add_parser('command_a', help='command_a help')
parser_a.add_argument('bar', type=int, help='bar help')

# create the parser for the "command_b" command
parser_b = subparsers.add_parser('command_b', help='command_b help')
parser_b.add_argument('--baz', choices='XYZ', help='baz help')

# parse some argument lists
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_argsparse_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')

# create the parser for the "command_a" command
parser_a = subparsers.add_parser('command_a', help='command_a help')
parser_a.add_argument('bar', type=int, help='bar help')

# create the parser for the "command_b" command
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)
#options = parser.parse_args(['--help'])

उपयोग जानकारी में विभिन्न आदेशों को सूचीबद्ध करना संभव है, मेरा उत्तर https://stackoverflow.com/a/49999185/428542 देखें


4

आप arghandler की कोशिश कर सकते हैं । यह उप-क्षेत्र के लिए स्पष्ट समर्थन के साथ बढ़ने का विस्तार है।


3
सबगैंड्स घोषित करने के लिए arghandler एक अच्छा तरीका प्रदान करता है। हालाँकि, मैं यह नहीं देखता कि यह ओपी के प्रश्न को हल करने में कैसे मदद करता है: एकाधिक उप-पार्कों को पार्स करना । पहले उप-क्रम पार्स किए गए सभी शेष तर्क खा जाएंगे, इसलिए आगे की आज्ञाओं को कभी भी पार्स नहीं किया जाएगा। कृपया इस बात का संकेत दें कि इसे कैसे हल करें। धन्यवाद।
एड्रियन डब्ल्यू

1

एक अन्य पैकेज जो समानांतर पार्सर का समर्थन करता है, वह है "घोषणात्मक_पर"।

import argparse
from declarative_parser import Parser, Argument

supported_formats = ['png', 'jpeg', 'gif']

class InputParser(Parser):
    path = Argument(type=argparse.FileType('rb'), optional=False)
    format = Argument(default='png', choices=supported_formats)

class OutputParser(Parser):
    format = Argument(default='jpeg', choices=supported_formats)

class ImageConverter(Parser):
    description = 'This app converts images'

    verbose = Argument(action='store_true')
    input = InputParser()
    output = OutputParser()

parser = ImageConverter()

commands = '--verbose input image.jpeg --format jpeg output --format gif'.split()

namespace = parser.parse_args(commands)

और नाम स्थान बन जाता है:

Namespace(
    input=Namespace(format='jpeg', path=<_io.BufferedReader name='image.jpeg'>),
    output=Namespace(format='gif'),
    verbose=True
)

डिस्क्लेमर: मैं लेखक हूं। अजगर 3.6 की आवश्यकता है। उपयोग स्थापित करने के लिए:

pip3 install declarative_parser

यहाँ प्रलेखन है और यहाँ GitHub पर रेपो है


1

सबपर्सर्स के साथ एक पूर्ण पायथन 2/3 उदाहरण बनाया , parse_known_argsऔर parse_args( IDEone पर चल रहा है ):

from __future__ import print_function

from argparse import ArgumentParser
from random import randint


def main():
    parser = get_parser()

    input_sum_cmd = ['sum_cmd', '--sum']
    input_min_cmd = ['min_cmd', '--min']

    args, rest = parser.parse_known_args(
        # `sum`
        input_sum_cmd +
        ['-a', str(randint(21, 30)),
         '-b', str(randint(51, 80))] +
        # `min`
        input_min_cmd +
        ['-y', str(float(randint(64, 79))),
         '-z', str(float(randint(91, 120)) + .5)]
    )

    print('args:\t ', args,
          '\nrest:\t ', rest, '\n', sep='')

    sum_cmd_result = args.sm((args.a, args.b))
    print(
        'a:\t\t {:02d}\n'.format(args.a),
        'b:\t\t {:02d}\n'.format(args.b),
        'sum_cmd: {:02d}\n'.format(sum_cmd_result), sep='')

    assert rest[0] == 'min_cmd'
    args = parser.parse_args(rest)
    min_cmd_result = args.mn((args.y, args.z))
    print(
        'y:\t\t {:05.2f}\n'.format(args.y),
        'z:\t\t {:05.2f}\n'.format(args.z),
        'min_cmd: {:05.2f}'.format(min_cmd_result), sep='')

def get_parser():
    # create the top-level parser
    parser = ArgumentParser(prog='PROG')
    subparsers = parser.add_subparsers(help='sub-command help')

    # create the parser for the "sum" command
    parser_a = subparsers.add_parser('sum_cmd', help='sum some integers')
    parser_a.add_argument('-a', type=int,
                          help='an integer for the accumulator')
    parser_a.add_argument('-b', type=int,
                          help='an integer for the accumulator')
    parser_a.add_argument('--sum', dest='sm', action='store_const',
                          const=sum, default=max,
                          help='sum the integers (default: find the max)')

    # create the parser for the "min" command
    parser_b = subparsers.add_parser('min_cmd', help='min some integers')
    parser_b.add_argument('-y', type=float,
                          help='an float for the accumulator')
    parser_b.add_argument('-z', type=float,
                          help='an float for the accumulator')
    parser_b.add_argument('--min', dest='mn', action='store_const',
                          const=min, default=0,
                          help='smallest integer (default: 0)')
    return parser


if __name__ == '__main__':
    main()

0

मेरे पास कमोबेश एक जैसी आवश्यकताएं थीं: वैश्विक तर्क निर्धारित करने में सक्षम होना और कमांड लाइन के क्रम में उन्हें निष्पादित करना और उन्हें निष्पादित करना

मैं निम्नलिखित कोड के साथ समाप्त हुआ। मैंने इस और अन्य थ्रेड्स से कोड के कुछ हिस्सों का उपयोग किया।

# argtest.py
import sys
import argparse

def init_args():

    def parse_args_into_namespaces(parser, commands):
        '''
        Split all command arguments (without prefix, like --) in
        own namespaces. Each command accepts extra options for
        configuration.
        Example: `add 2 mul 5 --repeat 3` could be used to a sequencial
                 addition of 2, then multiply with 5 repeated 3 times.
        '''
        class OrderNamespace(argparse.Namespace):
            '''
            Add `command_order` attribute - a list of command
            in order on the command line. This allows sequencial
            processing of arguments.
            '''
            globals = None
            def __init__(self, **kwargs):
                self.command_order = []
                super(OrderNamespace, self).__init__(**kwargs)

            def __setattr__(self, attr, value):
                attr = attr.replace('-', '_')
                if value and attr not in self.command_order:
                    self.command_order.append(attr)
                super(OrderNamespace, self).__setattr__(attr, value)

        # Divide argv by commands
        split_argv = [[]]
        for c in sys.argv[1:]:
            if c in commands.choices:
                split_argv.append([c])
            else:
                split_argv[-1].append(c)

        # Globals arguments without commands
        args = OrderNamespace()
        cmd, args_raw = 'globals', split_argv.pop(0)
        args_parsed = parser.parse_args(args_raw, namespace=OrderNamespace())
        setattr(args, cmd, args_parsed)

        # Split all commands to separate namespace
        pos = 0
        while len(split_argv):
            pos += 1
            cmd, *args_raw = split_argv.pop(0)
            assert cmd[0].isalpha(), 'Command must start with a letter.'
            args_parsed = commands.choices[cmd].parse_args(args_raw, namespace=OrderNamespace())
            setattr(args, f'{cmd}~{pos}', args_parsed)

        return args


    #
    # Supported commands and options
    #
    parser = argparse.ArgumentParser(formatter_class=argparse.ArgumentDefaultsHelpFormatter)

    parser.add_argument('--print', action='store_true')

    commands = parser.add_subparsers(title='Operation chain')

    cmd1_parser = commands.add_parser('add', formatter_class=argparse.ArgumentDefaultsHelpFormatter)
    cmd1_parser.add_argument('add', help='Add this number.', type=float)
    cmd1_parser.add_argument('-r', '--repeat', help='Repeat this operation N times.',
                                               default=1, type=int)

    cmd2_parser = commands.add_parser('mult', formatter_class=argparse.ArgumentDefaultsHelpFormatter)
    cmd2_parser.add_argument('mult', help='Multiply with this number.', type=float)
    cmd2_parser.add_argument('-r', '--repeat', help='Repeat this operation N times.',
                                               default=1, type=int)

    args = parse_args_into_namespaces(parser, commands)
    return args


#
# DEMO
#

args = init_args()

# print('Parsed arguments:')
# for cmd in args.command_order:
#     namespace = getattr(args, cmd)
#     for option_name in namespace.command_order:
#         option_value = getattr(namespace, option_name)
#         print((cmd, option_name, option_value))

print('Execution:')
result = 0
for cmd in args.command_order:
    namespace = getattr(args, cmd)
    cmd_name, cmd_position = cmd.split('~') if cmd.find('~') > -1 else (cmd, 0)
    if cmd_name == 'globals':
        pass
    elif cmd_name == 'add':
        for r in range(namespace.repeat):
            if args.globals.print:
                print(f'+ {namespace.add}')
            result = result + namespace.add
    elif cmd_name == 'mult':
        for r in range(namespace.repeat):
            if args.globals.print:
                print(f'* {namespace.mult}')
            result = result * namespace.mult
    else:
        raise NotImplementedError(f'Namespace `{cmd}` is not implemented.')
print(10*'-')
print(result)

एक उदाहरण के नीचे:

$ python argstest.py --print add 1 -r 2 mult 5 add 3 mult -r 5 5

Execution:
+ 1.0
+ 1.0
* 5.0
+ 3.0
* 5.0
* 5.0
* 5.0
* 5.0
* 5.0
----------
40625.0

-4

आप पैकेज ऑप्टपर्स का उपयोग कर सकते हैं

import optparse
parser = optparse.OptionParser()
parser.add_option("-f", dest="filename", help="corpus filename")
parser.add_option("--alpha", dest="alpha", type="float", help="parameter alpha", default=0.5)
(options, args) = parser.parse_args()
fname = options.filename
alpha = options.alpha

1
यह वास्तव में इस सवाल का जवाब नहीं है। इसके अलावा, ऑप्टपर्स को पदावनत किया जाता है ( अजगर के डॉक्स से "ऑप्टपर्स मॉड्यूल को हटा दिया जाता है और इसे आगे विकसित नहीं किया जाएगा; अर्गपर्स मॉड्यूल के साथ विकास जारी रहेगा")।
क्रिस

डाउनवोट के लिए क्षमा करें, लेकिन यह मेरे द्वारा पूछे गए प्रश्न को संबोधित नहीं कर रहा है।
विकास
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.