How to add optional or once arguments?

How to add an argument that is optional and cannot be specified multiple times?

Really:

$ ./my.py $ ./my.py --arg MyArgValue 

Invalid:

 $ ./my.py --arg MyArgValue --arg ThisIsNotValid 

If I add an argument like:

 parser.add_argument('--arg', type=str) 

An invalid example results in the string ThisIsNotValid . I would expect a parser error.

+4
source share
4 answers

Create a custom action that throws an exception if the same argument is displayed twice. When the analyzer catches an exception, it prints a usage message and a well-formatted error message.

 import argparse class Highlander(argparse.Action): def __call__(self, parser, namespace, values, option_string=None): if getattr(namespace, self.dest, None) is not None: raise argparse.ArgumentError(self, 'There can be only one.') setattr(namespace, self.dest, values) parser = argparse.ArgumentParser() parser.add_argument('-f', action=Highlander) print (parser.parse_args('-f 1 -f 2'.split())) 
+3
source

It sounds like a hacker solution, but you get what you want. Use append action :

 parser.add_argument('-arg', type=str, action='append') args = parser.parse_args() if len(args.arg) > 1: sys.exit("Only one argument is allowed for '-arg'") elif len(args.arg) == 1: # elif is because it is valid for the length to be 0 args.arg = args.arg[0] 

The append action will create a command-line list consisting of all values, from all times this argument has been called. If the length of this list is greater than one, an error has occurred.

This way you can get values ​​from the command line, and if there are more than one, you can catch this as an error and notify the user.

+1
source

You can use this to get the number of occurrences with this, and get an error if it is more than one.

'append' - Here the list is stored and each argument value is added to the list. This is useful if you need to specify a parameter several times. Usage example:

 import argparse import sys parser = argparse.ArgumentParser() parser.add_argument('-arg', type='str', action='append') args = parser.parse_args() if len(args.arg) > 1: sys.exit('Invalid') MyArgValue = args.arg[0] 

The documentation for 'append' can be found here for more information:

http://docs.python.org/dev/library/argparse.html#action

Unfortunately, there is no easy way with argparse. This is probably because this is not a common use case. Typically, this counter is used for Boolean cases, for example, in detail mode. When you have extra lines, such as compilers with paths included, etc., they are usually followed.

Perhaps you can also use nargs and just use args.arg_name [0] and ignore the rest. Here you can find the nargs documentation for this:

http://docs.python.org/dev/library/argparse.html#nargs

0
source

I tested a solution using mutually_exclusive_group . The idea is to define a group that includes --arg twice. The parser maintains a list of seen_non_default_actions and checks for conflicts with an exclusive group before taking action on a new line of the argument. If --arg already on this list, the next call will conflict with it and cause an error.

There are several problems with this approach.

1) existing actions cannot be added to the new group mutually-excluding_groups. At fooobar.com/questions/797096 / ... I illustrate a scrap that circumvents this. He also refers to the proposed patch, which makes this easier.

2) currently parse_args adds the action to the list seen_non_default_actions , and then checks for conflicts. This means that the first --arg will conflict with itself. The solution is to switch the order. Check for conflicts first, then add the action to the list.

 import my_argparse as argparse # use a customized argparse parser = argparse.ArgumentParser(prog="PROG", formatter_class=argparse.MultiGroupHelpFormatter) # use a custom formatter than can handle overlapping groups action = parser.add_argument('--arg', help='use this argument only once') # define a group with two copies of this action as per patch issue10984 group = parser.add_mutually_exclusive_group(action, action) args = parser.parse_args() 

When called with various arguments, it creates:

 $ python3 test.py -h usage: PROG [-h] [--arg ARG | --arg ARG] optional arguments: -h, --help show this help message and exit --arg ARG use this argument only once $ python3 test.py --arg test Namespace(arg='test') $ python3 test.py --arg test --arg next usage: PROG [-h] [--arg ARG | --arg ARG] PROG: error: argument --arg: not allowed with argument --arg 

I am surprised, although this is an intuitive way of saying, "Use this argument only once." Does the use string use [--arg ARG | --arg ARG] [--arg ARG | --arg ARG] is this? And is the argument --arg: not allowed with argument --arg error message argument --arg: not allowed with argument --arg ?

0
source

Source: https://habr.com/ru/post/1261297/


All Articles