OR using argparse with two command line variables in Python

I have a program that accepts a file as an input file, whether it works with the contents of the file and pushes it to the server. I want to add an optional command line switch to indicate a dry run of a program in which it executes the entire crunch of the file but skips writing to the server. I use argparse to enter command line arguments, but I see no way to execute the "OR" function between the arguments. That's what I'm more or less looking for ...

Valid parameters:

1) prog.py inputfile server_name

2) prog.py inputfile -d

3) prog.py inputfile -d server_name

Dissallowed:

1) input file prog.py

I want to make sure that the server name is "OR" on the command line . And if both are there ... that's OK too. (therefore, is OR, not XOR). If I use mutually exclusive code with required = true, I can get XOR; but I can’t figure out how to do this as an “OR,” where both can be present. To complicate matters, the server name is a positional argument, and the dry run flag is an optional argument that can be anywhere on the command line. Does anyone have an idea on how to do this?

+5
source share
3 answers

Here is what I will do:

import argparse

parser = argparse.ArgumentParser()
parser.add_argument('-d', '--dry-run', action='store_true')
parser.add_argument('input_file', type=argparse.FileType('r'))
parser.add_argument('servername', nargs='?')

args = parser.parse_args()
if args.servername is None and not args.dry_run:
    parser.error("Option 'servername' is required when not in dry-run mode.")

print args

Examples:

$ ./prog.py inputfile servername
Namespace(dry_run=False, input_file=<open file 'inputfile', mode 'r' at 0x283440>, servername='servername')
$ ./prog.py inputfile -d
Namespace(dry_run=True, input_file=<open file 'inputfile', mode 'r' at 0x2cf440>, servername=None)
$ ./prog.py -d inputfile servername
Namespace(dry_run=True, input_file=<open file 'inputfile', mode 'r' at 0x1f4440>, servername='servername')
$ ./prog.py inputfile
usage: prog.py [-h] [-d] input_file [servername]
prog.py: error: Option 'servername' is required when not in dry-run mode.

You can also do this with a special action, and it has the same effect:

class ServernameAction(argparse.Action):
    def __call__(self, parser, namespace, values, option_string=None):
        if values is None and not namespace.dry_run:
            parser.error("Option 'servername' is required when not in dry-run mode.")
        setattr(namespace, self.dest, values)

...
parser.add_argument('servername', nargs='?', action=ServernameAction)
...
+5
source

argparse , , . :

parser = argparse.ArgumentParser(epilog='Either foo or bar (or both) must be specified.')
parser.add_argument('--foo', help='do something.')
parser.add_argument('--bar', help='do something else.')
args = vars(parser.parse_args())
if not args['foo'] and not args['bar']:
  parser.error('Either foo or bar (or both) must be specified.')
+3

Since the server name is ignored if used -d, give it a default value that will certainly cause an error if you try to use it (you still need to check it):

p.add_argument("server", default=None)

If set -d, you will probably never be able to both confirm or use the server name, and everything will be fine. Otherwise, your code will catch the failed server name when it tries to verify it.

0
source

All Articles