agrynchuk
agrynchuk

Reputation: 4937

As in argparse use mutually exclusive arguments?

A must-read list of some data (eg email addresses) from the command line:

some_util -l [email protected] [email protected]

or from a file:

some_util -L email.lst

How to make that not be able to use a combination of two key -l and -L in argparse

import argparse
import sys
def createCLParser():
    parser = argparse.ArgumentParser()
    parser.add_argument('-l', '--list', nargs='+', help='list from comand line')
    parser.add_argument('-L', '--list-file', type=argparse.FileType(), help='list from file')
    return parser
if __name__ == '__main__':
    parser = createCLParser()
    namespace = parser.parse_args(sys.argv[1:])

In argparse is a method add_mutually_exclusive_group () but it must be optional.

Upvotes: 1

Views: 686

Answers (2)

Robᵩ
Robᵩ

Reputation: 168626

Use the .add_mutually_exclusive_group() method with required=True:

import argparse
import sys
def createCLParser():
    parser = argparse.ArgumentParser()
    group = parser.add_mutually_exclusive_group(required=True)
    group.add_argument('-l', '--list', nargs='+', help='list from comand line')
    group.add_argument('-L', '--list-file', type=argparse.FileType(), help='list from file')

    return parser
if __name__ == '__main__':
    parser = createCLParser()
    namespace = parser.parse_args(sys.argv[1:])
    print namespace

Usage:

$ python ar.py 
usage: ar.py [-h] (-l LIST [LIST ...] | -L LIST_FILE)
ar.py: error: one of the arguments -l/--list -L/--list-file is required

$ python ar.py -l [email protected]
Namespace(list=['[email protected]'], list_file=None)

$ python ar.py -l [email protected] -L bar
usage: ar.py [-h] (-l LIST [LIST ...] | -L LIST_FILE)
ar.py: error: argument -L/--list-file: not allowed with argument -l/--list

Upvotes: 1

chepner
chepner

Reputation: 531205

Because one of them is required, this use case is better suited for subcommands:

some_util fromList [email protected] [email protected]

or

some_util fromFile email.lst

The code would resemble

import argparse

parser = argparse.ArgumentParser()
subparsers = parser.add_subparsers()
addr_parser = subparsers.add_parser("fromList")
file_parser = subparsers.add_parser("fromFile")

addr_parser.add_argument("addresses", nargs="+")
addr_parser.setdefaults(command="fromList")
file_parser.add_argument("address_file")
file_parser.setdefaults(command="fromFile")

parser.set_defaults(
args = parser.parse_args()

if args.command == "fromList":
    # use args.addresses
elif args.command == "fromFile":
    # read addresses from file named by args.address_file

Upvotes: 0

Related Questions