Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Argparse: How to accept any number of optional arguments (starting with `-` or `--`)

I'm trying to create a command line tool (let's call it 'X') that wraps another tool (let's call it 'Y').

I handle some cases specially, and add some options of myself, but I want to redirect whatever I don't want to handle to the tool Y.

So far I managed to redirect the arguments that don't come with dashes, for example X Y option1 option2 option3 will just call Y option1 option2 option3. I did this by adding a subparser Y and an argument any to it

Here's the code (x.py):

main_parser = argparse.ArgumentParser()
subparsers = main_parser.add_subparsers(dest="parser_name")

y_subparser = subparsers.add_parser('y')
y_options = y_subparser.add_argument('any', nargs='*')

Then in my handler code, i do this:

args = main_parser.parse_args()
if args.parser_name == 'y':
    command_string = ' '.join(['y'] + sys.argv[2:])
    os.system(command_string)

When I call python x.py y asdf zxcv qwer it works.

When I call python x.py y asdf zxcv qwer -option I get the error x.py: error: unrecognized arguments: -option

I realize that if stuff just gets too complicated with argparse i can always fall back to using sys.argv, but if you know this to be doable, please share.

I've also been looking through the argparse code, which is a little dense, and where it seems that ArgumentParser._parse_known_args does everything (300 lines). But before I go deeper, I thought maybe someone knows how to do this - if not, i'll post my discoveries here if someone else has the same problem.

like image 775
vlad-ardelean Avatar asked Jul 15 '15 08:07

vlad-ardelean


People also ask

How do you add Argparse optional arguments?

After importing the library, argparse. ArgumentParser() initializes the parser so that you can start to add custom arguments. To add your arguments, use parser. add_argument() .

How do I make Argparse argument optional in Python?

Python argparse optional argument The example adds one argument having two options: a short -o and a long --ouput . These are optional arguments. The module is imported. An argument is added with add_argument .

What is Store_true in Python?

The store_true option automatically creates a default value of False. Likewise, store_false will default to True when the command-line argument is not present. The source for this behavior is succinct and clear: http://hg.python.org/cpython/file/2.7/Lib/argparse.py#l861.


1 Answers

From the doc of argparse, you can use argparse.REMAINDER :

>>> parser = argparse.ArgumentParser(prog='PROG')
>>> parser.add_argument('--foo')
>>> parser.add_argument('command')
>>> parser.add_argument('args', nargs=argparse.REMAINDER)
>>> print(parser.parse_args('--foo B cmd --arg1 XX ZZ'.split()))
Namespace(args=['--arg1', 'XX', 'ZZ'], command='cmd', foo='B')

This work even with dashed in the subcommand arguments

>>> parser = argparse.ArgumentParser(prog='PROG')
>>> parser.add_argument('--foo')
>>> parser.add_argument('command')
>>> parser.add_argument('args', nargs=argparse.REMAINDER)
>>> print(parser.parse_args('--foo B cmd --arg1 XX ZZ --foobar'.split()))
Namespace(args=['--arg1', 'XX', 'ZZ', '--foobar'], command='cmd', foo='B')
like image 155
Patrick Avatar answered Oct 21 '22 20:10

Patrick