How to have sub-parser arguments in separate namespace with argparse?

前端 未结 2 1285
失恋的感觉
失恋的感觉 2021-01-11 21:44

I have the following test-code

import argparse
parser = argparse.ArgumentParser()
parser.add_argument(\"--verbose\", default = 0, type=int)

subparsers = par         


        
相关标签:
2条回答
  • 2021-01-11 22:02

    I have started to develop a different approach (but similar to the suggestion by Anthon) and come up with a much shorter code. However, I am not sure my approach is a general solution for the problem.

    To similar what Anthon is proposing, I define a new method which creates a list of 'top-level' arguments which are kept in args, while all the other arguments are returned as an additional dictionary:

    class MyArgumentParser(argparse.ArgumentParser):
        def parse_subargs(self, *args, **kw):
            # parse as usual
            args = argparse.ArgumentParser.parse_args(self, *args, **kw)
    
            # extract the destination names for top-level arguments
            topdest = [action.dest for action in parser._actions]
    
            # loop over all arguments given in args
            subargs = {}
            for key, value in args.__dict__.items():
    
                # if sub-parser argument found ...
                if key not in topdest:
    
                    # ... remove from args and add to dictionary
                    delattr(args,key)
                    subargs[key] = value
    
            return args, subargs
    

    Comments on this approach welcome, especially any loopholes I overlooked.

    0 讨论(0)
  • 2021-01-11 22:06

    You need to go into the bowels of argparse a bit but changing your script to the following should do the trick:

    import argparse
    from argparse import _HelpAction, _SubParsersAction
    
    class MyArgumentParser(argparse.ArgumentParser):
        def parse_args(self, *args, **kw):
            res = argparse.ArgumentParser.parse_args(self, *args, **kw)
            from argparse import _HelpAction, _SubParsersAction
            for x in parser._subparsers._actions:
                if not isinstance(x, _SubParsersAction):
                    continue
                v = x.choices[res.parser_name] # select the subparser name
                subparseargs = {}
                for x1 in v._optionals._actions: # loop over the actions
                    if isinstance(x1, _HelpAction): # skip help
                        continue
                    n = x1.dest
                    if hasattr(res, n): # pop the argument
                        subparseargs[n] = getattr(res, n)
                        delattr(res, n)
                res.subparseargs = subparseargs
            return res
    
    parser = MyArgumentParser()
    parser.add_argument("--verbose", default = 0, type=int)
    
    subparsers = parser.add_subparsers(dest = "parser_name")
    
    parser_lan = subparsers.add_parser('car')
    parser_lan.add_argument("--boo")
    parser_lan.add_argument("--foo")
    
    parser_serial = subparsers.add_parser('bus')
    parser_serial.add_argument("--fun")
    
    print parser.parse_args()
    
    0 讨论(0)
提交回复
热议问题