Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Add arguments to argparse depending on value of initial arguments

I know similar questions have been asked before but I could not really find an exact one (also, I could not understand the 'nargs' or 'subparse' concept and how it would apply to my case)

I want something like:

parser = argparse.ArgumentParser()
parser.add_argument('-mode', choices=['download', 'upload'], required=True)
parser.add_argument('-d', required=True)
args = parser.parse_args()
if args.mode == 'download':
    parser.add_argument('-f', required=True)

args = parser.parse_args()

so the -f argument is required only when the -mode is download otherwise it should not be parsed

like image 515
Lyman Zerga Avatar asked Sep 09 '13 22:09

Lyman Zerga


People also ask

How do you add arguments in Argparse?

To add your arguments, use parser. add_argument() . Some important parameters to note for this method are name , type , and required . The name is exactly what it sounds like — the name of the command line field.

What are positional and optional arguments in Argparse?

Python argparse optional argument These are optional arguments. The module is imported. An argument is added with add_argument . The action set to store_true will store the argument as True , if present.

Which of the following parameters is set to specify that passing an argument is mandatory while adding the argument to a created parser?

required is a parameter of the ArugmentParser object's function add_argument() . By default, the arguments of type -f or --foo are optional and can be omitted. If a user is required to make an argument, they can set the keyword argument required to True .

What is action Store_true in Argparse?

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

Generally, you should avoid making --options required. In this case, I would suggest the following:

  1. Replace --mode with a subcommand.
  2. Replace -d with a positional argument
  3. Replace -f with a 2nd positional argument for the download command only.

If you really want to, you can keep -d and -f instead of making them positional arguments.

Your calls would look like this:

./script.py upload d-argument
./script.py download d-argument f-argument

or

./script.py upload -d foo
./script.py download -d foo -f bar

The code to implement is a little tedious, but fairly straightforward.

parser = argparse.ArgumentParser()
subparsers = parser.add_subparsers()
upload_parser = subparsers.add_parser('upload')
download_parser = subparsers.add_parser('download')
upload_parser.set_defaults(cmd='upload')
download_parser.set_defaults(cmd='download')
for p in [ upload_parser, download_parser ]:
    p.add_argument("d")
    # p.add_argument("-d", required=True)
download_parser.add_argument("f")
# download_parser.add_argument("-f", required=True)


args = parser.parse_args()
if args.cmd == 'upload':
    # handle upload with args.d
elif args.cmd == 'download':
    # handle download with args.d and args.f

Note the calls to set_defaults used to mark in the final parsed arguments which command was used.

like image 68
chepner Avatar answered Sep 28 '22 17:09

chepner